SpatialGridPointModel.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/SpatialGridPointModel.h>
00026 #include <sofa/component/collision/CubeModel.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <vector>
00029 #include <sofa/helper/system/gl.h>
00030
00031 namespace sofa
00032 {
00033
00034 namespace component
00035 {
00036
00037 namespace collision
00038 {
00039
00040 SOFA_DECL_CLASS(SpatialGridPointModel)
00041
00042 int SpatialGridPointModelClass = core::RegisterObject("Collision model which represents a set of points, spatially grouped using a SpatialGridContainer")
00043 .add< SpatialGridPointModel >()
00044 ;
00045
00046 SpatialGridPointModel::SpatialGridPointModel()
00047 : d_leafScale(initData(&d_leafScale,0,"leafScale","at which level should the first cube layer be constructed.\nNote that this must not be greater than GRIDDIM_LOG2"))
00048 , grid(NULL)
00049 {
00050 }
00051
00052 void SpatialGridPointModel::init()
00053 {
00054 this->PointModel::init();
00055 this->getContext()->get(grid);
00056
00057 if (grid==NULL)
00058 {
00059 std::cerr << "ERROR: SpatialGridPointModel requires a Vec3 SpatialGridContainer.\n";
00060 return;
00061 }
00062 }
00063
00064 bool SpatialGridPointModel::OctreeSorter::operator()(const Grid::Key& k1, const Grid::Key& k2)
00065 {
00066 for (int scale = root_shift; scale >= 0; --scale)
00067 {
00068 for (int c=k1.size()-1;c>=0;--c)
00069 {
00070 if ((k1[c]>>scale) < (k2[c]>>scale))
00071 return true;
00072 if ((k1[c]>>scale) > (k2[c]>>scale))
00073 return false;
00074 }
00075 }
00076
00077 return false;
00078 }
00079
00080 void SpatialGridPointModel::computeBoundingTree(int maxDepth)
00081 {
00082 if (!grid)
00083 {
00084 this->PointModel::computeBoundingTree(maxDepth);
00085 return;
00086 }
00087 const bool verbose = this->f_printLog.getValue();
00088 int lscale = d_leafScale.getValue();
00089 if (lscale > Grid::GRIDDIM_LOG2) lscale = Grid::GRIDDIM_LOG2;
00090 int ldim = (1<<lscale);
00091 int nleaf = Grid::GRIDDIM/ldim;
00092 CubeModel* cubeModel = createPrevious<CubeModel>();
00093 const int npoints = mstate->getX()->size();
00094 bool updated = false;
00095 if (npoints != size)
00096 {
00097 resize(npoints);
00098 updated = true;
00099 }
00100 if (updated) cubeModel->resize(0);
00101 if (!isMoving() && !cubeModel->empty() && !updated) return;
00102
00103 std::vector<OctreeCell> cells;
00104 Grid* g = grid->getGrid();
00105 Grid::const_iterator itgbegin = g->gridBegin();
00106 Grid::const_iterator itgend = g->gridEnd();
00107
00108 bool sorted = true;
00109 for (Grid::const_iterator itg = itgbegin; itg != itgend; ++itg)
00110 {
00111 Grid::Key k = itg->first;
00112 Grid::Grid* g = itg->second;
00113 if (g->empty) continue;
00114 for (int z0 = 0; z0<nleaf; z0++)
00115 for (int y0 = 0; y0<nleaf; y0++)
00116 for (int x0 = 0; x0<nleaf; x0++)
00117 {
00118 int pfirst = -1;
00119 int plast = -1;
00120 Grid::Key k2;
00121 k2[0] = k[0]*nleaf + x0;
00122 k2[1] = k[1]*nleaf + y0;
00123 k2[2] = k[2]*nleaf + z0;
00124 for (int z = 0; z<ldim; z++)
00125 for (int y = 0; y<ldim; y++)
00126 for (int x = 0; x<ldim; x++)
00127 {
00128 Grid::Cell* c = g->cell+((z0*ldim+z)*Grid::DZ+(y0*ldim+y)*Grid::DY+(x0*ldim+x)*Grid::DX);
00129 if (!c->plist.empty())
00130 {
00131 if (pfirst==-1)
00132 pfirst = c->plist.front().index;
00133 else if (c->plist.front().index != plast+1)
00134 sorted = false;
00135 plast = c->plist.back().index;
00136 if (c->plist.back().index - c->plist.front().index +1 != (int)c->plist.size())
00137 sorted = false;
00138 }
00139 }
00140 if (pfirst == -1) continue;
00141 cells.push_back(OctreeCell(k2, pfirst, plast));
00142
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 }
00170 if (!sorted)
00171 {
00172 std::cerr << "ERROR(SpatialGridPointModel): points are not sorted in spatial grid."<<std::endl;
00173 }
00174
00175 cubeModel->resize(cells.size());
00176 if (cells.empty()) return;
00177 OctreeSorter s(maxDepth);
00178 Vector3::value_type cellSize = g->getCellWidth()*ldim;
00179 std::sort(cells.begin(), cells.end(), s);
00180
00181
00182 for (unsigned int i=0;i<cells.size();i++)
00183 {
00184 Grid::Key k = cells[i].k;
00185
00186 int pfirst = cells[i].pfirst;
00187 int plast = cells[i].plast;
00188 Vector3 minElem, maxElem;
00189 for (unsigned int c=0;c<k.size();++c)
00190 {
00191 minElem[c] = k[c]*cellSize;
00192 maxElem[c] = (k[c]+1)*cellSize;
00193 }
00194 cubeModel->setLeafCube(i, std::make_pair(Iterator(this,pfirst),Iterator(this,plast+1)), minElem, maxElem);
00195 }
00196
00197
00198 int depth = 0;
00199 while (depth < maxDepth && cells.size() > 8)
00200 {
00201 if (verbose) std::cout << "SpatialGridPointModel: cube depth "<<depth<<": "<<cells.size()<<" cells ("<<(size*100/cells.size())*0.01<<" points/cell)."<<std::endl;
00202
00203 int parent = -1;
00204 for (unsigned int i=0;i<cells.size();++i)
00205 {
00206 Grid::Key k = cells[i].k;
00207
00208 for (unsigned int c=0;c<k.size();++c)
00209 k[c] >>= 1;
00210 if (parent == -1 || !(k == cells[parent].k))
00211 {
00212
00213 ++parent;
00214 cells[parent].k = k;
00215 cells[parent].pfirst = i;
00216 cells[parent].plast = i;
00217 }
00218 else
00219 {
00220 cells[parent].plast = i;
00221 }
00222 }
00223
00224 if (cells.size() > (unsigned int)parent+1)
00225 {
00226 cells.resize(parent+1);
00227 CubeModel* prevCubeModel = cubeModel;
00228 cubeModel = cubeModel->createPrevious<CubeModel>();
00229 cubeModel->resize(0);
00230 for (unsigned int i=0;i<cells.size();++i)
00231 {
00232 Grid::Key k = cells[i].k;
00233 int pfirst = cells[i].pfirst;
00234 int plast = cells[i].plast;
00235 Cube cfirst(prevCubeModel, pfirst);
00236 Cube clast(prevCubeModel, plast);
00237 cubeModel->addCube(Cube(prevCubeModel,pfirst),Cube(prevCubeModel,plast+1));
00238 }
00239 }
00240 ++depth;
00241 }
00242 CubeModel* root = cubeModel->createPrevious<CubeModel>();
00243 while (dynamic_cast<CubeModel*>(root->getPrevious()) != NULL)
00244 {
00245 root = dynamic_cast<CubeModel*>(root->getPrevious());
00246 }
00247 root->resize(0);
00248 root->addCube(Cube(cubeModel,0), Cube(cubeModel,cubeModel->getSize()));
00249 }
00250
00251 }
00252
00253 }
00254
00255 }
00256