00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdpacs.h"
00027
00028 #include "pacs/chain_quad.h"
00029
00030 using namespace std;
00031 using namespace NLMISC;
00032
00033
00034 namespace NLPACS
00035 {
00036
00037
00038
00039 const float CChainQuad::_QuadElementSize= 4;
00040
00041
00042
00043 CChainQuad::CChainQuad()
00044 {
00045 _QuadData= NULL;
00046 _QuadDataLen= 0;
00047 }
00048
00049 CChainQuad::~CChainQuad()
00050 {
00051 delete [] _QuadData;
00052 _QuadData= NULL;
00053 _QuadDataLen= 0;
00054 }
00055
00056 CChainQuad::CChainQuad(const CChainQuad &o)
00057 {
00058 _QuadData= NULL;
00059 _QuadDataLen= 0;
00060 *this= o;
00061 }
00062
00063 CChainQuad &CChainQuad::operator=(const CChainQuad &o)
00064 {
00065
00066 _QuadDataLen= o._QuadDataLen;
00067 delete [] _QuadData;
00068 if(_QuadDataLen>0)
00069 {
00070 _QuadData= (uint8*)new uint8[_QuadDataLen];
00071
00072 memcpy(_QuadData, o._QuadData, _QuadDataLen);
00073 }
00074 else
00075 _QuadData= NULL;
00076
00077
00078 _Width= o._Width;
00079 _Height= o._Height;
00080 _X= o._X;
00081 _Y= o._Y;
00082
00083
00084 _Quad.clear();
00085 _Quad.resize(o._Quad.size(), NULL);
00086 for(sint i=0; i<(sint)_Quad.size(); i++)
00087 {
00088 if(o._Quad[i])
00089 {
00090 uint32 off= (uint32)(o._Quad[i]-o._QuadData);
00091 _Quad[i]= _QuadData+off;
00092 }
00093 }
00094
00095
00096 return *this;
00097 }
00098
00099
00100
00101
00102 void CChainQuad::getGridBounds(sint32 &x0, sint32 &y0, sint32 &x1, sint32 &y1, const CVector &minP, const CVector &maxP) const
00103 {
00104 x0= (sint32)floor(minP.x / _QuadElementSize) - _X;
00105 y0= (sint32)floor(minP.y / _QuadElementSize) - _Y;
00106 x1= (sint32) ceil(maxP.x / _QuadElementSize) - _X;
00107 y1= (sint32) ceil(maxP.y / _QuadElementSize) - _Y;
00108
00109 if(x1-x0==0)
00110 x0--, x1++;
00111 if(y1-y0==0)
00112 y0--, y1++;
00113
00114 x0= max(x0, (sint32)0);
00115 y0= max(y0, (sint32)0);
00116 x1= min(x1, (sint32)_Width);
00117 y1= min(y1, (sint32)_Height);
00118 }
00119
00120
00121
00122 void CChainQuad::build(const std::vector<COrderedChain> &ochains)
00123 {
00124 vector< list<CEdgeChainEntry> > tempQuad;
00125 sint i,j;
00126
00127
00128 contReset(_Quad);
00129 delete [] _QuadData;
00130 _QuadData= NULL;
00131 _QuadDataLen= 0;
00132
00133
00134
00135
00136 bool first=true;
00137 CAABBox chainquadBBox;
00138
00139 for(i=0;i<(sint)ochains.size();i++)
00140 {
00141 const std::vector<CVector2s> &vertices= ochains[i].getVertices();
00142
00143
00144 for(j= 0; j<(sint)vertices.size();j++)
00145 {
00146
00147 if(first)
00148 first= false, chainquadBBox.setCenter(vertices[j].unpack3f());
00149 else
00150 chainquadBBox.extend(vertices[j].unpack3f());
00151 }
00152 }
00153
00154
00155 _X= (sint32)floor(chainquadBBox.getMin().x / _QuadElementSize);
00156 _Y= (sint32)floor(chainquadBBox.getMin().y / _QuadElementSize);
00157 _Width= (sint32)ceil(chainquadBBox.getMax().x / _QuadElementSize) - _X;
00158 _Height= (sint32)ceil(chainquadBBox.getMax().y / _QuadElementSize) - _Y;
00159
00160 tempQuad.resize(_Width*_Height);
00161 _Quad.resize(_Width*_Height, NULL);
00162
00163
00164
00165
00166
00167 for(i=0;i<(sint)ochains.size();i++)
00168 {
00169 const std::vector<CVector2s> &vertices= ochains[i].getVertices();
00170
00171 sint numEdges= (sint)vertices.size()-1;
00172
00173
00174 for(j= 0; j<numEdges; j++)
00175 {
00176 const CVector p0= vertices[j].unpack3f();
00177 const CVector p1= vertices[j+1].unpack3f();
00178 CVector minP,maxP;
00179 minP.minof(p0, p1);
00180 maxP.maxof(p0, p1);
00181
00182 if(minP.x-maxP.x==0)
00183 minP.x-=0.001f, maxP.x+=0.001f;
00184 if(minP.y-maxP.y==0)
00185 minP.y-=0.001f, maxP.y+=0.001f;
00186
00187
00188
00189 sint32 x0, y0, x1, y1;
00190 getGridBounds(x0, y0, x1, y1, minP, maxP);
00191
00192
00193 for(sint y= y0; y<y1; y++)
00194 {
00195 for(sint x= x0; x<x1; x++)
00196 {
00197 list<CEdgeChainEntry> &quadNode= tempQuad[y*_Width+x];
00198
00199 addEdgeToQuadNode(quadNode, i, j);
00200 }
00201 }
00202 }
00203 }
00204
00205
00206
00207
00208 sint memSize= 0;
00209
00210 for(i=0;i<(sint)tempQuad.size();i++)
00211 {
00212 list<CEdgeChainEntry> &quadNode= tempQuad[i];
00213
00214 if(!quadNode.empty())
00215 {
00216
00217 memSize+= sizeof(uint16);
00218
00219 memSize+= quadNode.size()*sizeof(CEdgeChainEntry);
00220 }
00221 }
00222
00223
00224 _QuadData= (uint8*)new uint8[memSize];
00225 _QuadDataLen= memSize;
00226
00227
00228
00229
00230 uint8 *ptr= _QuadData;
00231 for(i=0;i<(sint)tempQuad.size();i++)
00232 {
00233 list<CEdgeChainEntry> &srcQuadNode= tempQuad[i];
00234 list<CEdgeChainEntry>::iterator it;
00235
00236 if(!srcQuadNode.empty())
00237 {
00238 _Quad[i]= ptr;
00239
00240
00241 uint16 len= srcQuadNode.size();
00242 *((uint16*)ptr)= len;
00243 ptr+= sizeof(uint16);
00244
00245
00246 it= srcQuadNode.begin();
00247 for(j=0; j<len; j++, it++)
00248 {
00249 *((CEdgeChainEntry*)ptr)= *it;
00250 ptr+= sizeof(CEdgeChainEntry);
00251 }
00252 }
00253 }
00254
00255
00256
00257 }
00258
00259
00260
00261 void CChainQuad::addEdgeToQuadNode(list<CEdgeChainEntry> &quadNode, sint ochainId, sint edgeId)
00262 {
00263
00264
00265 list<CEdgeChainEntry>::iterator it;
00266 for(it= quadNode.begin(); it!=quadNode.end();it++)
00267 {
00268 if(it->OChainId==ochainId)
00269 {
00270
00271 it->EdgeStart= min(it->EdgeStart, (uint16)edgeId);
00272 it->EdgeEnd= max(it->EdgeEnd, (uint16)(edgeId+1));
00273 return;
00274 }
00275 }
00276
00277
00278
00279
00280 CEdgeChainEntry entry;
00281 entry.OChainId= ochainId;
00282 entry.EdgeStart= edgeId;
00283 entry.EdgeEnd= edgeId+1;
00284 quadNode.push_back(entry);
00285 }
00286
00287
00288
00289 sint CChainQuad::selectEdges(const NLMISC::CAABBox &bbox, CCollisionSurfaceTemp &cst) const
00290 {
00291 sint nRes=0;
00292 sint i;
00293 uint16 *ochainLUT= cst.OChainLUT;
00294
00295
00296 cst.EdgeChainEntries.clear();
00297
00298
00299 sint32 x0, y0, x1, y1;
00300 getGridBounds(x0, y0, x1, y1, bbox.getMin(), bbox.getMax());
00301
00302
00303
00304 for(sint y= y0; y<y1; y++)
00305 {
00306 for(sint x= x0; x<x1; x++)
00307 {
00308 uint8 *quadNode= _Quad[y*_Width+x];
00309
00310
00311 if(!quadNode)
00312 continue;
00313
00314
00315 sint numEdgeChainEntries= *((uint16*)quadNode);
00316 quadNode+= sizeof(uint16);
00317 CEdgeChainEntry *ptrEdgeChainEntry= (CEdgeChainEntry*)quadNode;
00318
00319
00320 for(i=0;i<numEdgeChainEntries;i++)
00321 {
00322 uint16 ochainId= ptrEdgeChainEntry[i].OChainId;
00323
00324
00325 if(ochainLUT[ochainId]==0xFFFF)
00326 {
00327
00328 ochainLUT[ochainId]= nRes;
00329 cst.EdgeChainEntries.push_back(ptrEdgeChainEntry[i]);
00330 nRes++;
00331 }
00332 else
00333 {
00334
00335 uint16 id= ochainLUT[ochainId];
00336 CEdgeChainEntry &ece= cst.EdgeChainEntries[id];
00337 ece.EdgeStart= min(ece.EdgeStart, ptrEdgeChainEntry[i].EdgeStart);
00338 ece.EdgeEnd= max(ece.EdgeEnd, ptrEdgeChainEntry[i].EdgeEnd);
00339 }
00340 }
00341 }
00342 }
00343
00344
00345
00346 for(i=0;i<nRes;i++)
00347 {
00348 uint16 ochainId= cst.EdgeChainEntries[i].OChainId;
00349 ochainLUT[ochainId]= 0xFFFF;
00350 }
00351
00352
00353 return nRes;
00354 }
00355
00356 sint CChainQuad::selectEdges(CVector start, CVector end, CCollisionSurfaceTemp &cst) const
00357 {
00358 sint nRes=0;
00359 sint i;
00360 uint16 *ochainLUT= cst.OChainLUT;
00361
00362
00363 cst.EdgeChainEntries.clear();
00364
00365 if (end.x < start.x)
00366 swap(start, end);
00367
00368 float minx = _X*_QuadElementSize,
00369 miny = _Y*_QuadElementSize,
00370 maxx = minx + _Width*_QuadElementSize,
00371 maxy = miny + _Height*_QuadElementSize;
00372
00373 if (start.x > maxx || end.x < minx || start.y > maxy || end.y < miny)
00374 return nRes;
00375
00376 if (start.x < minx)
00377 {
00378 start.y = start.y+(end.y-start.y)*(minx-start.x)/(end.x-start.x);
00379 start.x = minx;
00380 }
00381
00382 if (start.y < miny)
00383 {
00384 start.x = start.x+(end.x-start.x)*(miny-start.y)/(end.y-start.y);
00385 start.y = miny;
00386 }
00387
00388 if (end.x > maxx)
00389 {
00390 end.y = start.y+(end.y-start.y)*(minx-start.x)/(end.x-start.x);
00391 end.x = maxx;
00392 }
00393
00394 if (end.y > maxy)
00395 {
00396 end.x = start.x+(end.x-start.x)*(miny-start.y)/(end.y-start.y);
00397 end.y = maxy;
00398 }
00399
00400 sint32 x0, x1, ya, yb;
00401 sint x, y;
00402 float fx, fxa, fxb, fya, fyb;
00403
00404 x0 = (sint32)floor(start.x / _QuadElementSize) - _X;
00405 x1 = (sint32)ceil(end.x / _QuadElementSize) - _X;
00406 fx = (x0+_X)*_QuadElementSize;
00407
00408 for (x=x0; x<x1; ++x)
00409 {
00410 fxa = (fx < start.x) ? start.x : fx;
00411 fxb = (fx+_QuadElementSize > end.x) ? end.x : fx+_QuadElementSize;
00412
00413 fya = start.y+(end.y-start.y)*(fxa-start.x)/(end.x-start.x);
00414 fyb = start.y+(end.y-start.y)*(fxb-start.x)/(end.x-start.x);
00415
00416 if (fya > fyb)
00417 swap (fya, fyb);
00418
00419 ya = (sint32)floor(fya / _QuadElementSize) - _Y;
00420 yb = (sint32)ceil(fyb / _QuadElementSize) - _Y;
00421
00422 fx += _QuadElementSize;
00423
00424 for (y=ya; y<yb; ++y)
00425 {
00426 uint8 *quadNode= _Quad[y*_Width+x];
00427
00428
00429 if(!quadNode)
00430 continue;
00431
00432
00433 sint numEdgeChainEntries= *((uint16*)quadNode);
00434 quadNode+= sizeof(uint16);
00435 CEdgeChainEntry *ptrEdgeChainEntry= (CEdgeChainEntry*)quadNode;
00436
00437
00438 for(i=0;i<numEdgeChainEntries;i++)
00439 {
00440 uint16 ochainId= ptrEdgeChainEntry[i].OChainId;
00441
00442
00443 if(ochainLUT[ochainId]==0xFFFF)
00444 {
00445
00446 ochainLUT[ochainId]= nRes;
00447 cst.EdgeChainEntries.push_back(ptrEdgeChainEntry[i]);
00448 nRes++;
00449 }
00450 else
00451 {
00452
00453 uint16 id= ochainLUT[ochainId];
00454 CEdgeChainEntry &ece= cst.EdgeChainEntries[id];
00455 ece.EdgeStart= min(ece.EdgeStart, ptrEdgeChainEntry[i].EdgeStart);
00456 ece.EdgeEnd= max(ece.EdgeEnd, ptrEdgeChainEntry[i].EdgeEnd);
00457 }
00458 }
00459 }
00460 }
00461
00462
00463 for(i=0;i<nRes;i++)
00464 {
00465 uint16 ochainId= cst.EdgeChainEntries[i].OChainId;
00466 ochainLUT[ochainId]= 0xFFFF;
00467 }
00468
00469 return nRes;
00470 }
00471
00472
00473 void CChainQuad::serial(NLMISC::IStream &f)
00474 {
00475
00476
00477
00478
00479 (void)f.serialVersion(0);
00480 uint i;
00481
00482
00483 f.serial(_X, _Y, _Width, _Height, _QuadDataLen);
00484
00485
00486
00487 if(f.isReading())
00488 {
00489 delete [] _QuadData;
00490 if(_QuadDataLen>0)
00491 _QuadData= (uint8*)new uint8[_QuadDataLen];
00492 else
00493 _QuadData= NULL;
00494 }
00495
00496 uint16 *ptrQData= (uint16*)_QuadData;
00497 for(i=0;i<_QuadDataLen/2; i++, ptrQData++)
00498 {
00499 f.serial(*ptrQData);
00500 }
00501
00502
00503
00504 std::vector<uint32> offsets;
00505 uint32 len;
00506 uint32 val;
00507 if(f.isReading())
00508 {
00509
00510 f.serial(len);
00511 offsets.resize(len);
00512 contReset(_Quad);
00513 _Quad.resize(len);
00514
00515
00516 for(i=0; i<len; i++)
00517 {
00518 f.serial(val);
00519 if(val== 0xFFFFFFFF)
00520 _Quad[i]= NULL;
00521 else
00522 _Quad[i]= _QuadData+val;
00523 }
00524 }
00525 else
00526 {
00527
00528 len= _Quad.size();
00529 f.serial(len);
00530
00531
00532 for(i=0; i<len; i++)
00533 {
00534 uint8 *ptr= _Quad[i];
00535 if(ptr==NULL)
00536 val= 0xFFFFFFFF;
00537 else
00538 val= (uint32)(ptr-_QuadData);
00539 f.serial(val);
00540 }
00541 }
00542
00543 }
00544
00545
00546
00547 }