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/edge_quad.h"
00029 #include "pacs/global_retriever.h"
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033
00034
00035 namespace NLPACS
00036 {
00037
00038
00039
00040 const float CEdgeQuad::_QuadElementSize= 4;
00041
00042
00043
00044 CEdgeQuad::CEdgeQuad()
00045 {
00046 _QuadData= NULL;
00047 _QuadDataLen= 0;
00048 }
00049
00050 CEdgeQuad::~CEdgeQuad()
00051 {
00052 clear();
00053 }
00054
00055 CEdgeQuad::CEdgeQuad(const CEdgeQuad &o)
00056 {
00057 _QuadData= NULL;
00058 _QuadDataLen= 0;
00059 *this= o;
00060 }
00061
00062 CEdgeQuad &CEdgeQuad::operator=(const CEdgeQuad &o)
00063 {
00064
00065 _QuadDataLen= o._QuadDataLen;
00066 delete [] _QuadData;
00067 if(_QuadDataLen>0)
00068 {
00069 _QuadData= (uint8*)new uint8[_QuadDataLen];
00070
00071 memcpy(_QuadData, o._QuadData, _QuadDataLen);
00072 }
00073 else
00074 _QuadData= NULL;
00075
00076
00077 _Width= o._Width;
00078 _Height= o._Height;
00079 _X= o._X;
00080 _Y= o._Y;
00081 _EdgeEntries = o._EdgeEntries;
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 void CEdgeQuad::clear()
00101 {
00102 delete [] _QuadData;
00103 _QuadData= NULL;
00104 _QuadDataLen= 0;
00105
00106 _Quad.clear();
00107 _EdgeEntries.clear();
00108 _Width = 0;
00109 _Height = 0;
00110 _X = 0;
00111 _Y = 0;
00112 }
00113
00114
00115 void CEdgeQuad::getGridBounds(sint32 &x0, sint32 &y0, sint32 &x1, sint32 &y1, const CVector &minP, const CVector &maxP) const
00116 {
00117 x0= (sint32)floor(minP.x / _QuadElementSize) - _X;
00118 y0= (sint32)floor(minP.y / _QuadElementSize) - _Y;
00119 x1= (sint32) ceil(maxP.x / _QuadElementSize) - _X;
00120 y1= (sint32) ceil(maxP.y / _QuadElementSize) - _Y;
00121 x0= max(x0, (sint32)0);
00122 y0= max(y0, (sint32)0);
00123 x1= min(x1, (sint32)_Width);
00124 y1= min(y1, (sint32)_Height);
00125 }
00126
00127
00128
00129
00130 void CEdgeQuad::build(const CExteriorMesh &em,
00131 const CGlobalRetriever &global,
00132 CCollisionSurfaceTemp &cst,
00133 uint32 thisInstance)
00134 {
00135 const std::vector<CExteriorMesh::CEdge> &edges = em.getEdges();
00136
00137 vector< list<uint16> > tempQuad;
00138 sint i, j;
00139
00140
00141 contReset(_Quad);
00142 delete [] _QuadData;
00143 _QuadData= NULL;
00144 _QuadDataLen= 0;
00145
00146
00147 CVector origin = global.getInstance(thisInstance).getOrigin();
00148
00149
00150
00151 bool first=true;
00152 CAABBox chainquadBBox;
00153
00154 for (i=0; i<(sint)edges.size()-1; i++)
00155 {
00156
00157 if (first)
00158 first= false, chainquadBBox.setCenter(edges[i].Start);
00159 else
00160 chainquadBBox.extend(edges[i].Start);
00161 }
00162
00163
00164 _X= (sint32)floor(chainquadBBox.getMin().x / _QuadElementSize);
00165 _Y= (sint32)floor(chainquadBBox.getMin().y / _QuadElementSize);
00166 _Width= (sint32)ceil(chainquadBBox.getMax().x / _QuadElementSize) - _X;
00167 _Height= (sint32)ceil(chainquadBBox.getMax().y / _QuadElementSize) - _Y;
00168
00169 tempQuad.resize(_Width*_Height);
00170 _Quad.resize(_Width*_Height, NULL);
00171
00172
00173
00174
00175
00176 for (i=0; i<(sint)edges.size()-1; i++)
00177 {
00178 float dnorm = (edges[i+1].Start-edges[i].Start).norm();
00179 uint numStep = (uint)(dnorm/0.1f)+1;
00180 uint step;
00181
00182 CVector pbegin = edges[i].Start+origin,
00183 pend = edges[i+1].Start+origin;
00184
00185 CVector opbegin = edges[i].Start,
00186 opend = edges[i+1].Start;
00187
00188 for (step=0; step<numStep; ++step)
00189 {
00190 float lambda0 = (float)(step)/(float)(numStep);
00191 float lambda1 = (float)(step+1)/(float)(numStep);
00192 CVector p0 = pbegin*(1.0f-lambda0)+pend*(lambda0),
00193 p1 = pbegin*(1.0f-lambda1)+pend*(lambda1);
00194 CVector op0 = opbegin*(1.0f-lambda0)+opend*(lambda0),
00195 op1 = opbegin*(1.0f-lambda1)+opend*(lambda1);
00196 CVector s0, s1,
00197 mins, maxs;
00198
00199 uint prevEdge = (i-1)%(edges.size()-1);
00200 bool prio0 = (edges[i].Link!=-1) || (edges[prevEdge].Link!=-1);
00201
00202 UGlobalPosition gp0 = global.retrievePosition(p0);
00203 global.updateHeight(gp0);
00204 UGlobalPosition gp1 = global.retrievePosition(p1);
00205 global.updateHeight(gp1);
00206
00207 if (!prio0)
00208 {
00209 swap(p0, p1);
00210 swap(op0, op1);
00211 swap(gp0, gp1);
00212 }
00213
00214 if (gp0.InstanceId == -1)
00215 {
00216 swap(p0, p1);
00217 swap(op0, op1);
00218 swap(gp0, gp1);
00219 }
00220
00221 const TCollisionSurfaceDescVector *pcd = global.testCylinderMove(gp0, p1-p0, 0.01f, cst);
00222
00223 if (pcd == NULL)
00224 {
00225
00226 continue;
00227 }
00228
00229 TCollisionSurfaceDescVector cd = (*pcd);
00230
00231 if (edges[i].Link != -1 && cd.size() > 0)
00232 {
00233 nlwarning ("In NLPACS::CEdgeQuad::build()");
00234 nlwarning ("ERROR: exterior edge %d with interior link crosses some surfaces", i);
00235 cd.clear ();
00236 }
00237
00238
00239 CCollisionSurfaceDesc stcd;
00240 stcd.ContactTime = 0.0f;
00241 stcd.ContactSurface.RetrieverInstanceId = gp0.InstanceId;
00242 stcd.ContactSurface.SurfaceId = gp0.LocalPosition.Surface;
00243 cd.insert(cd.begin(), stcd);
00244
00245
00246 sint edgeId = i;
00247 uint16 chainId;
00248
00249 CSurfaceIdent interior;
00250 if (edges[i].Link == -1)
00251 {
00252 interior.RetrieverInstanceId = -1;
00253 interior.SurfaceId = -1;
00254 chainId = 0xFFFF;
00255 }
00256 else
00257 {
00258 interior.RetrieverInstanceId = thisInstance;
00259 interior.SurfaceId = em.getLink(edges[i].Link).SurfaceId;
00260 chainId = em.getLink(edges[i].Link).ChainId;
00261 }
00262
00263
00264
00265 stcd = cd.back();
00266 stcd.ContactTime = 1.0f;
00267 cd.push_back(stcd);
00268
00269 for (j=0; j<(sint)cd.size()-1; ++j)
00270 {
00271 s0 = op0*(float)(1.0-cd[j].ContactTime) + op1*(float)(cd[j].ContactTime);
00272 s1 = op0*(float)(1.0-cd[j+1].ContactTime) + op1*(float)(cd[j+1].ContactTime);
00273
00274 mins.minof(s0, s1);
00275 maxs.maxof(s0, s1);
00276
00277
00278 if(mins.x-maxs.x==0)
00279 mins.x-=0.001f, maxs.x+=0.001f;
00280 if(mins.y-maxs.y==0)
00281 mins.y-=0.001f, maxs.y+=0.001f;
00282
00283
00284 sint32 x0, y0, x1, y1;
00285 sint x, y;
00286 getGridBounds(x0, y0, x1, y1, mins, maxs);
00287
00288 CSurfaceIdent exterior = cd[j].ContactSurface;
00289
00290 uint entry;
00291 for (entry=0; entry<_EdgeEntries.size(); ++entry)
00292 {
00293 if (_EdgeEntries[entry].EdgeId == edgeId &&
00294 _EdgeEntries[entry].Exterior == exterior)
00295 {
00296 if (_EdgeEntries[entry].ChainId != chainId ||
00297 _EdgeEntries[entry].Interior != interior)
00298 {
00299 nlwarning("In NLPACS::CEdgeQuad::build()");
00300 nlerror("exterior edge %d has different interior linkage", edgeId);
00301 }
00302
00303 break;
00304 }
00305 }
00306
00307
00308 if (entry == _EdgeEntries.size())
00309 {
00310 _EdgeEntries.push_back(CExteriorEdgeEntry());
00311 _EdgeEntries.back().EdgeId = edgeId;
00312 _EdgeEntries.back().ChainId = chainId;
00313 _EdgeEntries.back().Interior = interior;
00314 _EdgeEntries.back().Exterior = exterior;
00315 }
00316
00317
00318 for(y=y0; y<y1; y++)
00319 {
00320 for(x=x0; x<x1; x++)
00321 {
00322
00323 list<uint16>::iterator it;
00324 for (it=tempQuad[y*_Width+x].begin(); it!=tempQuad[y*_Width+x].end(); ++it)
00325 if (entry == *it)
00326 break;
00327 if (it == tempQuad[y*_Width+x].end())
00328 tempQuad[y*_Width+x].push_back(entry);
00329 }
00330 }
00331 }
00332 }
00333
00334 }
00335
00336 nlinfo("Built ExteriorEdgeQuad, linked following doors:");
00337 for (i=0; i<(sint)_EdgeEntries.size(); ++i)
00338 {
00339 if (edges[_EdgeEntries[i].EdgeId].Link != -1 &&
00340 (_EdgeEntries[i].Interior.RetrieverInstanceId == -1 || _EdgeEntries[i].Interior.SurfaceId == -1 ||
00341 _EdgeEntries[i].Exterior.RetrieverInstanceId == -1 || _EdgeEntries[i].Exterior.SurfaceId == -1))
00342 {
00343 nlwarning("In NLPACS::CEdgeQuad::build(): exterior door %d has corrupted link", i);
00344 }
00345 else if (edges[_EdgeEntries[i].EdgeId].Link != -1)
00346 {
00347 nlinfo("Inst=%d ExtEdge=%d IntInst=%d IntSurf=%d IntChain=%d ExtInst=%d ExtSurf=%d", thisInstance, _EdgeEntries[i].EdgeId,
00348 _EdgeEntries[i].Interior.RetrieverInstanceId, _EdgeEntries[i].Interior.SurfaceId, _EdgeEntries[i].ChainId,
00349 _EdgeEntries[i].Exterior.RetrieverInstanceId, _EdgeEntries[i].Exterior.SurfaceId);
00350 }
00351 }
00352
00353
00354
00355 sint memSize= 0;
00356
00357 for(i=0;i<(sint)tempQuad.size();i++)
00358 {
00359 list<uint16> &quadNode= tempQuad[i];
00360
00361 if(!quadNode.empty())
00362 {
00363
00364 memSize+= sizeof(uint16);
00365
00366 memSize+= quadNode.size()*sizeof(uint16);
00367 }
00368 }
00369
00370
00371 _QuadData= (uint8*)new uint8[memSize];
00372 _QuadDataLen= memSize;
00373
00374
00375
00376
00377 uint8 *ptr= _QuadData;
00378 for(i=0;i<(sint)tempQuad.size();i++)
00379 {
00380 list<uint16> &srcQuadNode= tempQuad[i];
00381 list<uint16>::iterator it;
00382
00383 if(!srcQuadNode.empty())
00384 {
00385 _Quad[i]= ptr;
00386
00387
00388 uint16 len= srcQuadNode.size();
00389 *((uint16*)ptr)= len;
00390 ptr+= sizeof(uint16);
00391
00392
00393 it= srcQuadNode.begin();
00394 for(j=0; j<len; j++, it++)
00395 {
00396 *((uint16 *)ptr)= *it;
00397 ptr+= sizeof(uint16);
00398 }
00399 }
00400 }
00401
00402
00403 }
00404
00405
00406
00407 sint CEdgeQuad::selectEdges(const NLMISC::CAABBox &bbox, CCollisionSurfaceTemp &cst) const
00408 {
00409 sint nRes=0;
00410 sint i;
00411 uint16 *indexLUT = cst.OChainLUT;
00412
00413
00414 cst.ExteriorEdgeIndexes.clear();
00415
00416
00417 sint32 x0, y0, x1, y1;
00418 getGridBounds(x0, y0, x1, y1, bbox.getMin(), bbox.getMax());
00419
00420
00421
00422 for (sint y= y0; y<y1; y++)
00423 {
00424 for (sint x= x0; x<x1; x++)
00425 {
00426 uint8 *quadNode= _Quad[y*_Width+x];
00427
00428
00429 if(!quadNode)
00430 continue;
00431
00432
00433 sint numExteriorEdgeIndexes= *((uint16*)quadNode);
00434 quadNode+= sizeof(uint16);
00435 uint16 *ptrExteriorEdgeIndex= (uint16*)quadNode;
00436
00437
00438 for (i=0;i<numExteriorEdgeIndexes;i++)
00439 {
00440 uint16 index = ptrExteriorEdgeIndex[i];
00441
00442
00443 if (indexLUT[index]==0xFFFF)
00444 {
00445
00446 indexLUT[index]= nRes;
00447 cst.ExteriorEdgeIndexes.push_back(index);
00448 nRes++;
00449 }
00450 }
00451 }
00452 }
00453
00454
00455
00456 for(i=0;i<nRes;i++)
00457 indexLUT[cst.ExteriorEdgeIndexes[i]]= 0xFFFF;
00458
00459 return nRes;
00460 }
00461
00462 sint CEdgeQuad::selectEdges(CVector start, CVector end, CCollisionSurfaceTemp &cst) const
00463 {
00464 sint nRes=0;
00465 sint i;
00466 uint16 *indexLUT= cst.OChainLUT;
00467
00468
00469 cst.ExteriorEdgeIndexes.clear();
00470
00471 if (end.x < start.x)
00472 swap(start, end);
00473
00474 float minx = _X*_QuadElementSize,
00475 miny = _Y*_QuadElementSize,
00476 maxx = minx + _Width*_QuadElementSize,
00477 maxy = miny + _Height*_QuadElementSize;
00478
00479 if (start.x > maxx || end.x < minx || start.y > maxy || end.y < miny)
00480 return nRes;
00481
00482 if (start.x < minx)
00483 {
00484 start.y = start.y+(end.y-start.y)*(minx-start.x)/(end.x-start.x);
00485 start.x = minx;
00486 }
00487
00488 if (start.y < miny)
00489 {
00490 start.x = start.x+(end.x-start.x)*(miny-start.y)/(end.y-start.y);
00491 start.y = miny;
00492 }
00493
00494 if (end.x > maxx)
00495 {
00496 end.y = start.y+(end.y-start.y)*(minx-start.x)/(end.x-start.x);
00497 end.x = maxx;
00498 }
00499
00500 if (end.y > maxy)
00501 {
00502 end.x = start.x+(end.x-start.x)*(miny-start.y)/(end.y-start.y);
00503 end.y = maxy;
00504 }
00505
00506 sint32 x0, x1, ya, yb;
00507 sint x, y;
00508 float fx, fxa, fxb, fya, fyb;
00509
00510 x0 = (sint32)floor(start.x / _QuadElementSize) - _X;
00511 x1 = (sint32)ceil(end.x / _QuadElementSize) - _X;
00512 fx = (x0+_X)*_QuadElementSize;
00513
00514 for (x=x0; x<x1; ++x)
00515 {
00516 fxa = (fx < start.x) ? start.x : fx;
00517 fxb = (fx+_QuadElementSize > end.x) ? end.x : fx+_QuadElementSize;
00518
00519 fya = start.y+(end.y-start.y)*(fxa-start.x)/(end.x-start.x);
00520 fyb = start.y+(end.y-start.y)*(fxb-start.x)/(end.x-start.x);
00521
00522 if (fya > fyb)
00523 swap (fya, fyb);
00524
00525 ya = (sint32)floor(fya / _QuadElementSize) - _Y;
00526 yb = (sint32)ceil(fyb / _QuadElementSize) - _Y;
00527
00528 fx += _QuadElementSize;
00529
00530 for (y=ya; y<yb; ++y)
00531 {
00532 uint8 *quadNode= _Quad[y*_Width+x];
00533
00534
00535 if(!quadNode)
00536 continue;
00537
00538
00539 sint numExteriorEdgeIndexes= *((uint16 *)quadNode);
00540 quadNode+= sizeof(uint16);
00541 uint16 *ptrExteriorEdgeIndex = (uint16 *)quadNode;
00542
00543
00544 for(i=0;i<numExteriorEdgeIndexes;i++)
00545 {
00546 uint16 index = ptrExteriorEdgeIndex[i];
00547
00548
00549 if(indexLUT[index]==0xFFFF)
00550 {
00551
00552 indexLUT[index]= nRes;
00553 cst.ExteriorEdgeIndexes.push_back(ptrExteriorEdgeIndex[i]);
00554 nRes++;
00555 }
00556 }
00557 }
00558 }
00559
00560
00561 for(i=0;i<nRes;i++)
00562 indexLUT[cst.ExteriorEdgeIndexes[i]]= 0xFFFF;
00563
00564 return nRes;
00565 }
00566
00567
00568 void CEdgeQuad::serial(NLMISC::IStream &f)
00569 {
00570
00571
00572
00573
00574 (void)f.serialVersion(0);
00575 uint i;
00576
00577
00578 f.serial(_X, _Y, _Width, _Height, _QuadDataLen);
00579 f.serialCont(_EdgeEntries);
00580
00581
00582 if(f.isReading())
00583 {
00584 delete [] _QuadData;
00585 if(_QuadDataLen>0)
00586 _QuadData= (uint8*)new uint8[_QuadDataLen];
00587 else
00588 _QuadData= NULL;
00589 }
00590
00591 uint16 *ptrQData= (uint16*)_QuadData;
00592 for(i=0;i<_QuadDataLen/2; i++, ptrQData++)
00593 {
00594 f.serial(*ptrQData);
00595 }
00596
00597
00598
00599 std::vector<uint32> offsets;
00600 uint32 len;
00601 uint32 val;
00602 if(f.isReading())
00603 {
00604
00605 f.serial(len);
00606 offsets.resize(len);
00607 contReset(_Quad);
00608 _Quad.resize(len);
00609
00610
00611 for(i=0; i<len; i++)
00612 {
00613 f.serial(val);
00614 if(val== 0xFFFFFFFF)
00615 _Quad[i]= NULL;
00616 else
00617 _Quad[i]= _QuadData+val;
00618 }
00619 }
00620 else
00621 {
00622
00623 len= _Quad.size();
00624 f.serial(len);
00625
00626
00627 for(i=0; i<len; i++)
00628 {
00629 uint8 *ptr= _Quad[i];
00630 if(ptr==NULL)
00631 val= 0xFFFFFFFF;
00632 else
00633 val= (uint32)(ptr-_QuadData);
00634 f.serial(val);
00635 }
00636 }
00637
00638 }
00639
00640
00641
00642 }