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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "OSGConfig.h"
00044 #include "OSGBalancedMultiWindow.h"
00045
00046 #include "OSGClusterNetwork.h"
00047 #include "OSGTransform.h"
00048 #include "OSGPerspectiveCamera.h"
00049 #include "OSGSolidBackground.h"
00050 #include "OSGMatrixUtility.h"
00051 #include "OSGRenderAction.h"
00052
00053 #include "OSGChunkMaterial.h"
00054 #include "OSGProxyGroup.h"
00055 #include "OSGGeometry.h"
00056 #include "OSGSimpleSHLChunk.h"
00057 #include "OSGTileCameraDecorator.h"
00058
00059 #include "OSGGLU.h"
00060
00061 OSG_BEGIN_NAMESPACE
00062
00065 static void multFullMatrixPnt4 (Matrix m, Pnt4f &p)
00066 {
00067 Pnt4f tmp;
00068
00069 tmp[0] = m[0][0]*p[0] + m[1][0]*p[1] + m[2][0]*p[2] + m[3][0]*p[3];
00070 tmp[1] = m[0][1]*p[0] + m[1][1]*p[1] + m[2][1]*p[2] + m[3][1]*p[3];
00071 tmp[2] = m[0][2]*p[0] + m[1][2]*p[1] + m[2][2]*p[2] + m[3][2]*p[3];
00072 tmp[3] = m[0][3]*p[0] + m[1][3]*p[1] + m[2][3]*p[2] + m[3][3]*p[3];
00073
00074 p[0] = tmp[0];
00075 p[1] = tmp[1];
00076 p[2] = tmp[2];
00077 p[3] = tmp[3];
00078 }
00079
00080
00081
00082
00083
00088
00089
00090
00091
00092
00093
00094
00095
00096 void BalancedMultiWindow::initMethod(InitPhase ePhase)
00097 {
00098 Inherited::initMethod(ePhase);
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 BalancedMultiWindow::BalancedMultiWindow(void) :
00112 Inherited ( ),
00113 _rebuildLoadGroups(true)
00114 {
00115 }
00116
00117 BalancedMultiWindow::BalancedMultiWindow(const BalancedMultiWindow &source) :
00118 Inherited (source),
00119 _rebuildLoadGroups(true )
00120 {
00121 }
00122
00123 BalancedMultiWindow::~BalancedMultiWindow(void)
00124 {
00125 }
00126
00127 void BalancedMultiWindow::resolveLinks(void)
00128 {
00129 for(UInt32 i = 0; i < _cluster.rootNodes.size(); ++i)
00130 {
00131 _cluster.rootNodes[i] = NULL;
00132 }
00133
00134 for(UInt32 i = 0; i < _cluster.loadGroups.size(); ++i)
00135 {
00136 _cluster.loadGroups[i].root = NULL;
00137 _cluster.loadGroups[i].node = NULL;
00138 }
00139
00140 for(UInt32 i = 0; i < _cluster.servers.size(); ++i)
00141 {
00142 for(UInt32 j = 0; j < _cluster.servers[i].viewports.size(); ++j)
00143 {
00144 _cluster.servers[i].viewports[j].serverPort = NULL;
00145 _cluster.servers[i].viewports[j].root = NULL;
00146 }
00147 }
00148 }
00149
00150
00151
00152 void BalancedMultiWindow::changed(ConstFieldMaskArg whichField,
00153 UInt32 origin,
00154 BitVector details)
00155 {
00156 Inherited::changed(whichField, origin, details);
00157 }
00158
00159 void BalancedMultiWindow::dump( UInt32 ,
00160 const BitVector ) const
00161 {
00162 SLOG << "Dump BalancedMultiWindow NI" << std::endl;
00163 }
00164
00165
00166 void BalancedMultiWindow::serverInit(Window *pServerWindow, UInt32 id)
00167 {
00168 Inherited::serverInit(pServerWindow,id);
00169 }
00170
00171 void BalancedMultiWindow::serverRender(Window *pServerWindow,
00172 UInt32 id,
00173 RenderActionBase *action)
00174 {
00175 if(!getBalance())
00176 {
00177 _rebuildLoadGroups = true;
00178
00179 Inherited::serverRender(pServerWindow,id,action);
00180
00181 return;
00182 }
00183
00184 pServerWindow->activate ();
00185 pServerWindow->frameInit();
00186
00187
00188 glDisable(GL_SCISSOR_TEST);
00189 glViewport(0,0,
00190 pServerWindow->getWidth(),
00191 pServerWindow->getHeight());
00192 glClearColor(0,0,0,0);
00193 glClear(GL_COLOR_BUFFER_BIT);
00194
00195
00196 if(_cluster.servers.size() == 0)
00197 {
00198
00199 _cluster.servers.resize(getMFServers()->size() + 1);
00200 _cluster.servers[id].id = id;
00201
00202 getNetwork()->connectAllGroupToPoint(id,"StreamSock");
00203
00204
00205 for(UInt32 i=0 ; i <= getMFServers()->size() ; ++i)
00206 getNetwork()->getConnection(i)->forceDirectIO();
00207
00208 _preloadCache = true;
00209 }
00210
00211 UInt32 count,vp,vpcount,wpcount;
00212 Server &server = _cluster.servers[id];
00213 std::vector<WorkPackage>::iterator wI;
00214 std::vector<Area>::iterator aI;
00215 std::vector<Tile>::iterator tI;
00216
00217
00218 server.window = pServerWindow;
00219
00220
00221 createLoadGroups();
00222
00223
00224 preloadCache(pServerWindow,action);
00225
00226 _loadTime = -getSystemTime();
00227
00228
00229 collectVisibleViewports(server);
00230
00231
00232 createBBoxes(server);
00233
00234 _loadTime += getSystemTime();
00235
00236
00237 Connection *conn = getNetwork()->getMainConnection();
00238 vpcount = server.viewports.size();
00239 conn->putValue(id);
00240 conn->putValue(vpcount);
00241 for(vp=0 ; vp<vpcount ; ++vp)
00242 {
00243 VPort &port = server.viewports[vp];
00244 conn->putValue(port.id);
00245 conn->putValue(port.load);
00246 conn->putValues(port.loadCenter,2);
00247 conn->putValues(port.rect,4);
00248 count = port.bboxes.size();
00249 conn->putValue(count);
00250 if(count)
00251 conn->put(&port.bboxes[0],count*sizeof(BBox));
00252 }
00253 conn->flush();
00254
00255
00256 conn->selectChannel();
00257 conn->getValue(wpcount);
00258 _cluster.workpackages.resize(wpcount);
00259 if(wpcount)
00260 conn->get(&_cluster.workpackages[0],wpcount*sizeof(WorkPackage));
00261
00262 _cluster.areas.clear();
00263 drawSendAndRecv(pServerWindow,action,id);
00264
00265
00266 if(getShowBalancing())
00267 {
00268 conn = getNetwork()->getMainConnection();
00269 conn->putValue(_triCount);
00270 conn->putValue(_drawTime);
00271 conn->putValue(_pixelTime);
00272 conn->putValue(_loadTime);
00273 conn->putValue(_netTime);
00274 conn->flush();
00275 }
00276
00277 #if 0
00278
00279 glDisable(GL_SCISSOR_TEST);
00280 glViewport(0,0,
00281 pServerWindow->getWidth(),
00282 pServerWindow->getHeight());
00283 glPushMatrix();
00284 glLoadIdentity();
00285 glMatrixMode(GL_PROJECTION);
00286 glPushMatrix();
00287 glLoadIdentity();
00288 glOrtho(0, pServerWindow->getWidth(),
00289 0, pServerWindow->getHeight(), -1, 1);
00290
00291 for(UInt32 v=0; v<_cluster.servers[id].viewports.size() ; ++v)
00292 {
00293 for(UInt32 b=0; b<_cluster.servers[id].viewports[v].bboxes.size() ; ++b)
00294 {
00295 BBox &bbox = _cluster.servers[id].viewports[v].bboxes[b];
00296 glBegin(GL_LINE_LOOP);
00297 glColor3f(1, 1, 0);
00298 glVertex2f(bbox.rect[LEFT],bbox.rect[BOTTOM]);
00299 glVertex2f(bbox.rect[RIGHT],bbox.rect[BOTTOM]);
00300 glVertex2f(bbox.rect[RIGHT],bbox.rect[TOP]);
00301 glVertex2f(bbox.rect[LEFT],bbox.rect[TOP]);
00302 glEnd();
00303 }
00304 }
00305
00306 glPopMatrix();
00307 glMatrixMode(GL_MODELVIEW);
00308 glPopMatrix();
00309 #endif
00310 }
00311
00312 void BalancedMultiWindow::clientInit(void)
00313 {
00314 Inherited::clientInit();
00315 }
00316
00317 void BalancedMultiWindow::clientPreSync(void)
00318 {
00319 if(getHServers() * getVServers() == 0 && getClientWindow() != NULL)
00320 {
00321 if(getWidth () != getClientWindow()->getWidth () ||
00322 getHeight() != getClientWindow()->getHeight())
00323 {
00324 setWidth (getClientWindow()->getWidth ());
00325 setHeight(getClientWindow()->getHeight());
00326 }
00327 }
00328 Inherited::clientPreSync();
00329 }
00330
00331 void BalancedMultiWindow::clientRender(RenderActionBase *action)
00332 {
00333 if(!getBalance())
00334 {
00335 _rebuildLoadGroups = true;
00336 Inherited::clientRender(action);
00337 return;
00338 }
00339 Connection::Channel channel;
00340 UInt32 bbcount,id,vp,vpcount,wpcount;
00341 double frameTime = -getSystemTime();
00342
00343 if(_cluster.servers.size() == 0)
00344 {
00345
00346 _cluster.servers.resize(getMFServers()->size()+1);
00347
00348 for(UInt32 id=0 ; id < getMFServers()->size()+1 ; ++id)
00349 _cluster.servers[id].id = id;
00350
00351 getNetwork()->connectAllGroupToPoint(getMFServers()->size(),
00352 "StreamSock");
00353
00354
00355 for(UInt32 i=0 ; i <= getMFServers()->size() ; ++i)
00356 getNetwork()->getConnection(i)->forceDirectIO();
00357
00358 _preloadCache = true;
00359 }
00360
00361
00362 createLoadGroups();
00363
00364
00365 _loadTime = 0;
00366 if(getHServers() * getVServers() == 0 &&
00367 getClientWindow() != NULL)
00368 {
00369 _loadTime = -getSystemTime();
00370
00371 Server &server = _cluster.servers[getMFServers()->size()];
00372
00373
00374 server.window = getClientWindow();
00375
00376
00377 collectVisibleViewports(server);
00378
00379
00380 createBBoxes(server);
00381 _loadTime += getSystemTime();
00382
00383 for(vp=0 ; vp < server.viewports.size() ; ++vp)
00384 server.load += server.viewports[vp].load;
00385
00386
00387 preloadCache(getClientWindow(),action);
00388 }
00389
00390 _netTime = 0;
00391
00392 GroupConnection *conn = getNetwork()->getMainGroupConnection();
00393 while(conn->getSelectionCount())
00394 {
00395 channel = conn->selectChannel();
00396 conn->subSelection(channel);
00397 conn->getValue(id);
00398 conn->getValue(vpcount);
00399 Server &server = _cluster.servers[id];
00400 server.viewports.resize(vpcount);
00401 server.load = 0;
00402
00403 for(vp=0 ; vp < vpcount ; ++vp)
00404 {
00405 VPort &port = server.viewports[vp];
00406 port.serverId = id;
00407 conn->getValue(port.id);
00408 conn->getValue(port.load);
00409 conn->getValues(port.loadCenter,2);
00410 conn->getValues(port.rect,4);
00411 conn->getValue(bbcount);
00412 port.bboxes.resize(bbcount);
00413
00414
00415
00416
00417
00418
00419
00420
00421 if(bbcount)
00422 conn->get(&port.bboxes[0],bbcount*sizeof(BBox));
00423 server.load += port.load;
00424 }
00425 }
00426 conn->resetSelection();
00427
00428 _balanceTime = -getSystemTime();
00429 balanceServer();
00430 _balanceTime += getSystemTime();
00431
00432 wpcount = _cluster.workpackages.size();
00433 conn->putValue(wpcount);
00434 conn->put(&_cluster.workpackages[0],wpcount*sizeof(WorkPackage));
00435 conn->flush();
00436
00437
00438
00439 drawSendAndRecv(getClientWindow(),action,getMFServers()->size());
00440
00441
00442
00443 if(getHServers() * getVServers() != 0 &&
00444 getClientWindow() != NULL)
00445 {
00446 getClientWindow()->renderAllViewports( action );
00447 }
00448
00449
00450 UInt32 triCount;
00451 Real64 drawTime;
00452 Real64 pixelTime;
00453 Real64 loadTime;
00454 Real64 netTime;
00455 if(getShowBalancing())
00456 {
00457 printf("Statistics:\n");
00458 conn = getNetwork()->getMainGroupConnection();
00459 while(conn->getSelectionCount())
00460 {
00461 channel = conn->selectChannel();
00462 conn->subSelection(channel);
00463 conn->getValue(triCount);
00464 conn->getValue(drawTime);
00465 conn->getValue(pixelTime);
00466 conn->getValue(loadTime);
00467 conn->getValue(netTime);
00468 printf("Srv %4d L:%2.6lf T:%10d D:%2.6lf P:%2.6lf N:%2.6lf\n",channel,loadTime,triCount,drawTime,pixelTime,netTime);
00469 }
00470 conn->resetSelection();
00471 frameTime += getSystemTime();
00472 printf("Cli %4d L:%2.6lf T:%10d D:%2.6lf P:%2.6lf N:%2.6lf B:%2.6lf F:%2.6lf\n",
00473 getMFServers()->size(),
00474 _loadTime,
00475 _triCount,
00476 _drawTime,
00477 _pixelTime,
00478 _netTime,
00479 _balanceTime,
00480 frameTime);
00481 printf("end\n");
00482 }
00483 #if 0
00484 for(unsigned int p=0;p<_cluster.workpackages.size() ; ++p) {
00485 printf("from %d to %d %d %d %d %d\n",
00486 _cluster.workpackages[p].drawServer,
00487 _cluster.workpackages[p].sendToServer,
00488 _cluster.workpackages[p].rect[0],
00489 _cluster.workpackages[p].rect[1],
00490 _cluster.workpackages[p].rect[2],
00491 _cluster.workpackages[p].rect[3]);
00492 }
00493 #endif
00494 }
00495
00496
00499 UInt32 BalancedMultiWindow::calcTileCount(Int32 const (&rect)[4])
00500 {
00501 UInt32 x = (rect[RIGHT] - rect[LEFT ]) / MW_TILE_SIZE + 1;
00502 UInt32 y = (rect[TOP ] - rect[BOTTOM]) / MW_TILE_SIZE + 1;
00503 return x*y;
00504 }
00505
00508 bool BalancedMultiWindow::calculateProjectedBBox(VPort &port,
00509 LoadGroup &group,
00510 BBox &bbox,
00511 Matrix &proj)
00512 {
00513 Pnt3f vol[2];
00514 Pnt3f pnt3;
00515 Real32 minx=0,miny=0;
00516 Real32 maxx=0,maxy=0;
00517
00518 Int32 width = port.serverPort->getPixelWidth();
00519 Int32 height = port.serverPort->getPixelHeight();
00520 #if 1
00521 Matrix trans = group.node->getToWorld();
00522 trans.multLeft(proj);
00523
00524 Pnt4f pnt[8];
00525 Int32 cl=0, cb=0, cr=0, ct=0, cn=0, cf=0;
00526 Int32 bit = 1;
00527
00528
00529 BoxVolume volume = group.node->getVolume();
00530 #else
00531 Matrix trans = proj;
00532
00533 Pnt4f pnt[8];
00534 Int32 cl=0, cb=0, cr=0, ct=0, cn=0, cf=0;
00535 Int32 bit = 1;
00536
00537
00538 BoxVolume volume = group.node->getVolume();
00539 volume.transform(group.node->getToWorld());
00540
00541 #endif
00542 volume.getBounds (vol[0], vol[1]);
00543
00544 for(int i=0;i<8;++i)
00545 {
00546 pnt[i] = Pnt4f (vol[ (i )&1 ][0],
00547 vol[ (i>>1)&1 ][1],
00548 vol[ (i>>2)&1 ][2],
00549 1.0);
00550
00551 multFullMatrixPnt4 (trans, pnt[i]);
00552
00553
00554 if (pnt[i][0] >= -pnt[i][3]) cl += bit;
00555 if (pnt[i][0] <= pnt[i][3]) cr += bit;
00556 if (pnt[i][1] >= -pnt[i][3]) cb += bit;
00557 if (pnt[i][1] <= pnt[i][3]) ct += bit;
00558 if (pnt[i][2] >= -pnt[i][3]) cn += bit;
00559 if (pnt[i][2] <= pnt[i][3]) cf += bit;
00560
00561 bit *= 2;
00562 }
00563
00564
00565 if ((cl == 0) || (cb == 0) || (cr == 0) ||
00566 (ct == 0) || (cn == 0) || (cf == 0))
00567 {
00568 return false;
00569 }
00570
00571
00572 if (cn < 255)
00573 {
00574 bit = 1;
00575
00576 for (int i = 0; i < 8; ++i)
00577 {
00578
00579 if ((cn & bit) == 0)
00580 {
00581 pnt[i][0] = pnt[i][0] < 0 ? -1 : 1;
00582 pnt[i][1] = pnt[i][1] < 0 ? -1 : 1;
00583 pnt[i][2] = -1;
00584 pnt[i][3] = 1;
00585 }
00586
00587 bit *= 2;
00588 }
00589 }
00590
00591 for (int i = 0; i < 8; ++i)
00592 {
00593
00594 pnt[i][0] /= pnt[i][3];
00595 pnt[i][1] /= pnt[i][3];
00596
00597
00598 pnt[i][0] = (pnt[i][0] + 1) * width / 2.0;
00599 pnt[i][1] = (pnt[i][1] + 1) * height / 2.0;
00600
00601 if (i > 0)
00602 {
00603 if (minx > pnt[i][0]) minx = pnt[i][0];
00604 if (miny > pnt[i][1]) miny = pnt[i][1];
00605 if (maxx < pnt[i][0]) maxx = pnt[i][0];
00606 if (maxy < pnt[i][1]) maxy = pnt[i][1];
00607 }
00608 else
00609 {
00610 maxx = minx = pnt[i][0];
00611 maxy = miny = pnt[i][1];
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 bbox.rect[LEFT] = Int32(minx + port.serverPort->getPixelLeft ());
00621 bbox.rect[RIGHT] = Int32(maxx + port.serverPort->getPixelLeft ());
00622 bbox.rect[BOTTOM] = Int32(miny + port.serverPort->getPixelBottom ());
00623 bbox.rect[TOP] = Int32(maxy + port.serverPort->getPixelBottom ());
00624
00625 #if 0
00626
00627 glViewport(0,0,
00628 port.serverPort->getParent()->getWidth(),
00629 port.serverPort->getParent()->getHeight());
00630 glPushMatrix();
00631 glLoadIdentity();
00632 glMatrixMode(GL_PROJECTION);
00633 glPushMatrix();
00634 glLoadIdentity();
00635 glOrtho(0, port.serverPort->getParent()->getWidth(),
00636 0, port.serverPort->getParent()->getHeight(), -1, 1);
00637 glBegin(GL_LINE_LOOP);
00638 glColor3f(1, 1, 0);
00639 glVertex2f(bbox.rect[LEFT],bbox.rect[BOTTOM]);
00640 glVertex2f(bbox.rect[RIGHT],bbox.rect[BOTTOM]);
00641 glVertex2f(bbox.rect[RIGHT],bbox.rect[TOP]);
00642 glVertex2f(bbox.rect[LEFT],bbox.rect[TOP]);
00643 glEnd();
00644 glPopMatrix();
00645 glMatrixMode(GL_MODELVIEW);
00646 glPopMatrix();
00647 #endif
00648 return true;
00649 }
00650
00651
00652
00657 void BalancedMultiWindow::createLoadGroups(void)
00658 {
00659 Viewport *viewport;
00660 Node *root;
00661 UInt32 v;
00662
00663 if(!_rebuildLoadGroups)
00664 {
00665
00666 ChangeList *changeList = OSG::Thread::getCurrentChangeList();
00667
00668 if(changeList->getNumCreated () == 0 &&
00669 changeList->getNumDestroyed() == 0)
00670 {
00671 _rebuildLoadGroups = false;
00672 }
00673 else
00674 {
00675 _rebuildLoadGroups = true;
00676 }
00677 }
00678
00679 if(!_rebuildLoadGroups)
00680 return;
00681
00682 _preloadCache = true;
00683
00684
00685 _cluster.rootNodes.clear();
00686 _cluster.loadGroups.clear();
00687
00688 for(v = 0 ; v < getMFPort()->size() ; ++v )
00689 {
00690 viewport = getPort(v);
00691 root = viewport->getRoot();
00692
00693 #ifdef __sun
00694 UInt32 uiCount;
00695
00696 std::count(_cluster.rootNodes.begin(),
00697 _cluster.rootNodes.end(),
00698 root,
00699 uiCount);
00700
00701 if(uiCount)
00702 continue;
00703 #else
00704
00705 if(std::count(_cluster.rootNodes.begin(),
00706 _cluster.rootNodes.end(),
00707 root))
00708 continue;
00709 #endif
00710 _cluster.rootNodes.push_back(root);
00711
00712 collectLoadGroups(root,root);
00713 }
00714 _rebuildLoadGroups = false;
00715 }
00716
00717
00722 void BalancedMultiWindow::collectLoadGroups(Node *node, Node *root)
00723 {
00724 LoadGroup load;
00725 #if 0
00726 UInt32 lastSize;
00727 #endif
00728
00729 MFUnrecChildNodePtr::const_iterator child;
00730
00731
00732 if(node == NULL)
00733 return;
00734
00735 NodeCore *core = node->getCore();
00736 if(core != NULL)
00737 {
00738 Geometry *geo = NULL;
00739 ProxyGroup *proxy = NULL;
00740
00741 load.root = root;
00742 load.constant = 0;
00743 load.pixel = 0;
00744 load.ratio = 0;
00745 load.node = node;
00746
00747
00748 proxy = dynamic_cast<ProxyGroup *>(core);
00749 if(proxy != NULL)
00750 {
00751 load.constant = proxy->getIndices() / MW_INDICES_PER_SEC;
00752 load.ratio = proxy->getIndices() / MW_VISIBLE_INDICES_PER_SEC;
00753 }
00754 geo = dynamic_cast<Geometry *>(core);
00755 if(geo != NULL)
00756 {
00757 GeoIntegralProperty *indices =
00758 geo->getIndex(Geometry::PositionsIndex);
00759
00760 GeoVectorProperty *positions = geo->getPositions();
00761
00762 ChunkMaterial *mat =
00763 dynamic_cast<ChunkMaterial *> (geo->getMaterial ());
00764
00765
00766 if ((indices != NULL))
00767 {
00768 load.constant = indices->getSize() / MW_INDICES_PER_SEC;
00769 load.ratio = indices->getSize() / MW_VISIBLE_INDICES_PER_SEC;
00770 }
00771 else
00772 if(positions != NULL)
00773 {
00774 load.constant = positions->getSize() / MW_INDICES_PER_SEC;
00775 load.ratio = positions->getSize() / MW_VISIBLE_INDICES_PER_SEC;
00776 }
00777
00778 if (mat != NULL && mat->find (SimpleSHLChunk::getClassType ()) != NULL)
00779 load.pixel = 1.0f / Real32(MW_SHADED_PIXEL_PER_SEC);
00780 else
00781 load.pixel = 1.0f / Real32(MW_PIXEL_PER_SEC);
00782
00783 }
00784 if(load.pixel > 0 || load.constant > 0)
00785 _cluster.loadGroups.push_back(load);
00786 }
00787
00788 #if 0
00789 lastSize = _cluster.loadGroups.size();
00790 #endif
00791
00792 for(child = node->getMFChildren()->begin() ;
00793 child != node->getMFChildren()->end() ;
00794 ++child)
00795 {
00796 collectLoadGroups(*child,root);
00797 }
00798 #if 0
00799 if(lastSize + 1 < _cluster.loadGroups.size())
00800 {
00801 load.root = root;
00802 load.constant = 0;
00803 load.pixel = 0;
00804 load.node = node;
00805
00806 for(l = lastSize ; l < _cluster.loadGroups.size() ; ++l)
00807 {
00808 load.constant += _cluster.loadGroups[l].constant;
00809 load.pixel += _cluster.loadGroups[l].pixel;
00810 load.root = root;
00811 }
00812
00813 if(load.constant < 500.0 / MW_INDICES_PER_SEC &&
00814 load.pixel <= 1.0 / Real32(MW_PIXEL_PER_SEC))
00815 {
00816 _cluster.loadGroups.resize(lastSize);
00817 _cluster.loadGroups.push_back(load);
00818 }
00819 }
00820 #endif
00821 }
00822
00823
00826 void BalancedMultiWindow::collectVisibleViewports(Server &server)
00827 {
00828 UInt32 cv,sv=0;
00829
00830 for(cv = 0 ; cv < getMFPort()->size() ; cv++)
00831 {
00832 if(server.viewports.size() <= sv)
00833 server.viewports.resize(sv+1);
00834
00835 VPort &port = server.viewports[sv];
00836
00837 port.id = cv;
00838 port.serverId = server.id;
00839 port.root = getPort(cv)->getRoot();
00840 if(calculateServerPort(port,port.rect))
00841 sv++;
00842 }
00843
00844 server.viewports.resize(sv);
00845 }
00846
00847
00851 bool BalancedMultiWindow::calculateServerPort(VPort &port,
00852 Int32 const (&rect)[4])
00853 {
00854 Int32 cleft,cright,ctop,cbottom;
00855 Viewport *serverPort, *clientPort;
00856 TileCameraDecoratorUnrecPtr deco;
00857
00858
00859
00860 UInt32 row;
00861 UInt32 column;
00862 UInt32 width;
00863 UInt32 height;
00864 UInt32 rows,cols;
00865
00866 if(getHServers() * getVServers() == 0)
00867 {
00868 if(port.serverId != getMFServers()->size())
00869 return false;
00870
00871 rows = 1;
00872 cols = 1;
00873 row = 0;
00874 column = 0;
00875 }
00876 else
00877 {
00878 rows = getVServers();
00879 cols = getHServers();
00880 row = port.serverId/cols;
00881 column = port.serverId%cols;
00882 }
00883 width = getWidth() / cols;
00884 height = getHeight() / rows;
00885
00886 Int32 left = column * width - column * getXOverlap();
00887 Int32 bottom = row * height - row * getYOverlap();
00888 Int32 right = left + width - 1;
00889 Int32 top = bottom + height - 1;
00890 Real32 scaleCWidth = ((width - getXOverlap()) * (cols - 1) + width) /
00891 Real32(getWidth());
00892 Real32 scaleCHeight = ((height - getYOverlap())* (rows - 1) + height)/
00893 Real32(getHeight());
00894
00895 clientPort = getPort(port.id);
00896 cleft = Int32(clientPort->getPixelLeft() * scaleCWidth) ;
00897 cbottom = Int32(clientPort->getPixelBottom() * scaleCHeight) ;
00898 cright = Int32((clientPort->getPixelRight()+1) * scaleCWidth) -1;
00899 ctop = Int32((clientPort->getPixelTop()+1) * scaleCHeight)-1;
00900
00901 if(cright < left ||
00902 cleft > right ||
00903 ctop < bottom ||
00904 cbottom > top )
00905 {
00906
00907 return false;
00908 }
00909
00910 port.rect[LEFT] = osgMax(cleft ,left ) - left;
00911 port.rect[BOTTOM] = osgMax(cbottom,bottom) - bottom;
00912 port.rect[RIGHT] = osgMin(cright ,right ) - left;
00913 port.rect[TOP] = osgMin(ctop ,top ) - bottom;
00914
00915
00916 if(port.serverPort != NULL)
00917 {
00918 if(port.serverPort->getType().getId() != getPort(port.id)->getType().getId())
00919 {
00920
00921
00922
00923 port.serverPort = NULL;
00924 }
00925
00926 }
00927
00928
00929 if(port.serverPort == NULL)
00930 {
00931 ViewportUnrecPtr pTmpPort =
00932 dynamic_pointer_cast<Viewport>(getPort(port.id)->shallowCopy());
00933
00934 port.serverPort = pTmpPort;
00935
00936 deco = TileCameraDecorator::create();
00937 port.serverPort->setCamera(deco);
00938 }
00939 else
00940 {
00941 deco =
00942 dynamic_cast<TileCameraDecorator *>(port.serverPort->getCamera());
00943 }
00944
00945 deco->setDecoratee( clientPort->getCamera() );
00946
00947 serverPort = port.serverPort;
00948
00949
00950 serverPort->setSize(Real32(rect[LEFT]),
00951 Real32(rect[BOTTOM]),
00952 Real32(rect[RIGHT]),
00953 Real32(rect[TOP]));
00954
00955 if(serverPort->getLeft() == 1.0)
00956 serverPort->setLeft(1.0001f);
00957 if(serverPort->getRight() == 1.0)
00958 serverPort->setRight(1.0001f);
00959 if(serverPort->getTop() == 1.0)
00960 serverPort->setTop(1.0001f);
00961 if(serverPort->getBottom() == 1.0)
00962 serverPort->setBottom(1.0001f);
00963 serverPort->setRoot ( clientPort->getRoot() );
00964 serverPort->setBackground( clientPort->getBackground() );
00965 serverPort->assignForegrounds(*(clientPort->getMFForegrounds()) );
00966 serverPort->setTravMask ( clientPort->getTravMask() );
00967
00968
00969 #if 0
00970 deco->setFullWidth ( cright-cleft);
00971 deco->setFullHeight( ctop-cbottom);
00972 deco->setSize( ( rect[LEFT]+left-cleft ) / (float)( cright-cleft ),
00973 ( rect[BOTTOM]+bottom-cbottom ) / (float)( ctop-cbottom ),
00974 ( rect[RIGHT]+left-cleft ) / (float)( cright-cleft ),
00975 ( rect[TOP]+bottom-cbottom ) / (float)( ctop-cbottom ) );
00976 #else
00977 deco->setFullWidth ( cright-cleft + 1 );
00978 deco->setFullHeight( ctop-cbottom + 1 );
00979 deco->setSize( ( -(rect[LEFT]+left-cleft) ),
00980 ( -(rect[BOTTOM]+bottom-cbottom) ),
00981 ( -(rect[RIGHT]+left-cleft+1) ),
00982 ( -(rect[TOP]+bottom-cbottom+1) ) );
00983 #endif
00984 deco->setDecoratee( clientPort->getCamera() );
00985
00986 return true;
00987 }
00988
00989
00990
00993 void BalancedMultiWindow::createBBoxes(Server &server)
00994 {
00995 std::vector<VPort>::iterator vI;
00996 UInt32 gI;
00997 server.load = 0;
00998 UInt32 bbcount=0;
00999 Real32 load,sumLoad;
01000 Int32 bbmin[2];
01001 Int32 bbmax[2];
01002
01003 for(vI = server.viewports.begin() ; vI != server.viewports.end() ; ++vI)
01004 {
01005 bbmin[0] = vI->rect[RIGHT];
01006 bbmin[1] = vI->rect[TOP];
01007 bbmax[0] = vI->rect[LEFT];
01008 bbmax[1] = vI->rect[BOTTOM];
01009
01010
01011 server.window->addPort(vI->serverPort);
01012
01013
01014 Matrix viewing,projection,projectionTrans;
01015 Int32 width = vI->serverPort->getPixelWidth();
01016 Int32 height = vI->serverPort->getPixelHeight();
01017 vI->serverPort->getCamera()->getViewing (viewing, width, height);
01018 vI->serverPort->getCamera()->getProjection (projection, width, height);
01019 vI->serverPort->getCamera()->getProjectionTranslation( projectionTrans, width, height);
01020 projection.mult(projectionTrans);
01021 projection.mult(viewing);
01022
01023 sumLoad = 0;
01024 vI->loadCenter[0] = vI->loadCenter[1] = 0;
01025 for(gI = 0 ; gI != _cluster.loadGroups.size() ; ++gI)
01026 {
01027 LoadGroup &group = _cluster.loadGroups[gI];
01028 if(group.root == vI->root)
01029 {
01030 if(vI->bboxes.size() <= bbcount)
01031 vI->bboxes.resize(bbcount+1);
01032
01033 BBox &bbox = vI->bboxes[bbcount];
01034 bbox.groupId = gI;
01035
01036 if(calculateProjectedBBox(*vI,group,bbox,projection))
01037 {
01038
01039 load = getVisibleLoad(vI->rect,bbox);
01040 sumLoad += load;
01041 vI->loadCenter[0] += load*(bbox.rect[0]+bbox.rect[2])/2;
01042 vI->loadCenter[1] += load*(bbox.rect[1]+bbox.rect[3])/2;
01043 bbcount++;
01044 if(bbox.rect[LEFT] < bbmin[0])
01045 bbmin[0] = bbox.rect[LEFT];
01046 if(bbox.rect[BOTTOM] < bbmin[1])
01047 bbmin[1] = bbox.rect[BOTTOM];
01048 if(bbox.rect[RIGHT] > bbmax[0])
01049 bbmax[0] = bbox.rect[RIGHT];
01050 if(bbox.rect[TOP] > bbmax[1])
01051 bbmax[1] = bbox.rect[TOP];
01052 }
01053 }
01054 }
01055 vI->load = sumLoad;
01056 vI->bboxes.resize(bbcount);
01057 if(sumLoad)
01058 {
01059 vI->loadCenter[0] /= sumLoad;
01060 vI->loadCenter[1] /= sumLoad;
01061 }
01062
01063 if(bbmin[0] <= bbmax[0])
01064 {
01065 if(bbmin[0] > vI->rect[LEFT])
01066 vI->rect[LEFT] = bbmin[0];
01067 if(bbmax[0] < vI->rect[RIGHT])
01068 vI->rect[RIGHT] = bbmax[0];
01069 }
01070 if(bbmin[1] <= bbmax[1])
01071 {
01072 if(bbmin[1] > vI->rect[BOTTOM])
01073 vI->rect[BOTTOM] = bbmin[1];
01074 if(bbmax[1] < vI->rect[TOP])
01075 vI->rect[TOP] = bbmax[1];
01076 }
01077
01078
01079 server.window->subPortByObj(vI->serverPort);
01080 }
01081 }
01082
01085 void BalancedMultiWindow::balanceServer(void)
01086 {
01087 Worker wo;
01088 Int32 low,heigh;
01089 UInt32 serverId;
01090 UInt32 vI;
01091 Real32 tooMuch,medLoad,load=0;
01092 std::vector<Server*> server;
01093 std::vector<Worker> worker;
01094 ServerComp comp;
01095 Real32 tolerance;
01096 WorkPackage wp;
01097 UInt32 count;
01098
01099 if(getHServers()*getVServers() == 0)
01100 count = getMFServers()->size() + 1;
01101 else
01102 count = getMFServers()->size();
01103
01104
01105 _cluster.workpackages.clear();
01106
01107
01108
01109
01110
01111
01112 for(serverId = 0 ; serverId < count ; ++serverId)
01113 {
01114
01115 server.push_back(&_cluster.servers[serverId]);
01116 load += _cluster.servers[serverId].load;
01117 }
01118
01119 std::sort(server.begin(),server.end(),comp);
01120
01121 medLoad = load / count;
01122 low = 0;
01123 heigh = server.size() - 1;
01124 tolerance = medLoad * 0.1;
01125
01126 while(low < heigh && server[heigh]->load - tolerance > medLoad)
01127 {
01128 worker.clear();
01129
01130
01131 tooMuch = server[heigh]->load - medLoad;
01132 #if 0
01133
01134 if(server[heigh]->id == getServers().size())
01135 tooMuch = server[heigh]->load;
01136 #endif
01137 while(tooMuch > tolerance &&
01138 server[low]->load + tolerance < medLoad)
01139 {
01140
01141 wo.serverId = server[low]->id;
01142 wo.takeLoad = osgMin(tooMuch,medLoad - server[low]->load);
01143 worker.push_back(wo);
01144 tooMuch -= wo.takeLoad;
01145 server[heigh]->load -= wo.takeLoad;
01146 server[low]->load += wo.takeLoad;
01147 if(server[low]->load + tolerance >= medLoad)
01148 low++;
01149 }
01150 if(worker.size())
01151 {
01152
01153 wo.serverId = server[heigh]->id;
01154 wo.takeLoad = server[heigh]->load;
01155 worker.push_back(wo);
01156 for(vI = 0 ; vI < _cluster.servers[wo.serverId].viewports.size() ; ++vI)
01157 {
01158 VPort &port = _cluster.servers[wo.serverId].viewports[vI];
01159 splitViewport(worker,port,port.rect,port.load);
01160 #if 0
01161 for(int i=0 ; i<worker.size() ; ++i)
01162 {
01163 printf("%10.6f %10.6f\n",
01164 worker[i].takeLoad,
01165 worker[i].assignedLoad);
01166 server[worker[i].serverId]->load -= worker[i].takeLoad;
01167 server[worker[i].serverId]->load += worker[i].assignedLoad;
01168 }
01169 #endif
01170 }
01171 } else {
01172
01173 break;
01174 }
01175 #if 0
01176 if(server[low]->load + tolerance >= medLoad)
01177 {
01178 printf("Avoid overload\n");
01179 low++;
01180 }
01181 #endif
01182 heigh--;
01183 }
01184
01185 while(heigh >= 0)
01186 {
01187 for(vI = 0 ; vI < _cluster.servers[server[heigh]->id].viewports.size() ; ++vI)
01188 {
01189 VPort &port = _cluster.servers[server[heigh]->id].viewports[vI];
01190 wp.viewportId = port.id;
01191 wp.drawServer = server[heigh]->id;
01192 wp.sendToServer = server[heigh]->id;
01193 for(int i=0 ; i<4 ; ++i)
01194 wp.rect[i] = port.rect[i];
01195 _cluster.workpackages.push_back(wp);
01196 }
01197 heigh--;
01198 }
01199 #if 0
01200 for(int j=0;j<_cluster.workpackages.size() ; ++j)
01201 {
01202 printf("vp %d\n",_cluster.workpackages[j].viewportId);
01203 printf("render %d\n",_cluster.workpackages[j].drawServer);
01204 printf("display %d\n",_cluster.workpackages[j].sendToServer);
01205 printf("rect %d %d %d %d\n",
01206 _cluster.workpackages[j].rect[0],
01207 _cluster.workpackages[j].rect[1],
01208 _cluster.workpackages[j].rect[2],
01209 _cluster.workpackages[j].rect[3]);
01210 }
01211 #endif
01212 }
01213
01214
01217 void BalancedMultiWindow::splitViewport(std::vector<Worker> &allWorker,
01218 VPort &port,
01219 Int32 const (&rect)[4],
01220 Real32 portLoad)
01221 {
01222 UInt32 i;
01223 WorkPackage wp;
01224 std::vector<Worker>::iterator wI;
01225 Real32 load[2] = {0,0};
01226 std::vector<Worker> worker[2];
01227 Int32 localWorkerSide,side;
01228 Int32 localWorkerSideTry[2];
01229 Real32 resultLoad[2];
01230 Int32 resultRect[2][4];
01231 Real32 resultLoadTry[2][2];
01232 Int32 resultRectTry[2][2][4];
01233 UInt32 axis;
01234
01235
01236 UInt32 fromAxis,toAxis;
01237 bool bestCut=getBestCut();
01238
01239 if(rect[2] - rect[0] == 0 ||
01240 rect[3] - rect[1] == 0)
01241 {
01242 bestCut = false;
01243 }
01244
01245 localWorkerSide = -1;
01246 for(wI = allWorker.begin() ; wI != allWorker.end() ; ++wI)
01247 {
01248 if(load[0] <= load[1])
01249 side = 0;
01250 else
01251 side = 1;
01252
01253 load[side] += wI->takeLoad;
01254 worker[side].push_back(*wI);
01255
01256 if(wI->serverId == port.serverId)
01257 {
01258 localWorkerSide = side;
01259 }
01260 }
01261
01262
01263 Real32 scale = portLoad / (load[0] + load[1]);
01264 load[0] *= scale;
01265 load[1] *= scale;
01266
01267 if(bestCut)
01268 {
01269
01270 fromAxis=0;
01271 toAxis=1;
01272 }
01273 else
01274 {
01275
01276 if(rect[RIGHT] - rect[LEFT ] >
01277 rect[TOP ] - rect[BOTTOM])
01278 fromAxis = toAxis = 0;
01279 else
01280 fromAxis = toAxis = 1;
01281 }
01282
01283 for(axis = fromAxis ; axis <= toAxis ; ++axis)
01284 {
01285 if(localWorkerSide >= 0)
01286 {
01287 if(fabs(port.loadCenter[axis] - rect[LEFT +axis]) >
01288 fabs(port.loadCenter[axis] - rect[RIGHT+axis]))
01289
01290 localWorkerSideTry[axis] = 0;
01291 else
01292
01293 localWorkerSideTry[axis] = 1;
01294
01295 if(localWorkerSide != localWorkerSideTry[axis])
01296 {
01297 std::vector<Worker> w = worker[1];
01298 worker[1] = worker[0];
01299 worker[0] = w;
01300 Real32 l = load[1];
01301 load[1] = load[0];
01302 load[0] = l;
01303 localWorkerSide = localWorkerSideTry[axis];
01304 }
01305 }
01306 else
01307 localWorkerSideTry[axis] = localWorkerSide;
01308
01309 splitAxis(load,port,rect,axis,resultLoadTry[axis],resultRectTry[axis]);
01310 }
01311
01312
01313 if(bestCut)
01314 {
01315 if(osgMax(resultLoadTry[0][0],resultLoadTry[0][1]) <
01316 osgMax(resultLoadTry[1][0],resultLoadTry[1][1]))
01317 axis = 0;
01318 else
01319 axis = 1;
01320
01321
01322
01323
01324
01325 }
01326 else
01327 axis = fromAxis;
01328
01329
01330 if(localWorkerSideTry[axis] != localWorkerSide)
01331 {
01332 std::vector<Worker> w = worker[1];
01333 worker[1] = worker[0];
01334 worker[0] = w;
01335 Real32 l = load[1];
01336 load[1] = load[0];
01337 load[0] = l;
01338 localWorkerSide = localWorkerSideTry[axis];
01339 }
01340 resultLoad[0] = resultLoadTry[axis][0];
01341 resultLoad[1] = resultLoadTry[axis][1];
01342 for(i=0 ; i<4 ; ++i)
01343 {
01344 resultRect[0][i] = resultRectTry[axis][0][i];
01345 resultRect[1][i] = resultRectTry[axis][1][i];
01346 }
01347
01348
01349
01350
01351
01352
01353
01354 if( (worker[0].size() == 1 &&
01355 worker[1].size() == 1) &&
01356 #if 1
01357 (resultLoad[0] == 0.0 || resultLoad[1] == 0.0)
01358 #else
01359 ((resultLoad[0] + threshold) > (load[0] + load[1]) ||
01360 (resultLoad[1] + threshold) > (load[0] + load[1]))
01361 #endif
01362 )
01363 {
01364 bool toLeft = false;
01365 bool toRight = false;
01366
01367 if(localWorkerSide == 0)
01368 toLeft = true;
01369 else
01370 if(localWorkerSide == 1)
01371 toRight = true;
01372 else
01373 if(load[0] > load[1])
01374 toLeft = true;
01375 else
01376 if(load[0] <= load[1])
01377 toRight = true;
01378 if(toLeft)
01379 {
01380 resultLoad[0] = load[0] + load[1];
01381 resultLoad[1] = 0;
01382 resultRect[0][axis+2] = rect[axis+2];
01383 resultRect[1][axis] = rect[axis+2] + 1;
01384 }
01385 if(toRight)
01386 {
01387 resultLoad[0] = 0;
01388 resultLoad[1] = load[0] + load[1];
01389 resultRect[0][axis+2] = rect[axis] - 1;
01390 resultRect[1][axis] = rect[axis];
01391 }
01392 }
01393
01394 for(int g=0 ; g<2 ; ++g)
01395 {
01396
01397 if(resultRect[g][RIGHT] >= resultRect[g][LEFT] &&
01398 resultRect[g][TOP] >= resultRect[g][BOTTOM])
01399 {
01400 if(worker[g].size() > 1)
01401 splitViewport(worker[g],port,resultRect[g],resultLoad[g]);
01402 else
01403 {
01404
01405 worker[g][0].assignedLoad = resultLoad[g];
01406
01407 wp.viewportId = port.id;
01408 wp.drawServer = worker[g][0].serverId;
01409 wp.sendToServer = port.serverId;
01410 for(i=0 ; i<4 ; ++i)
01411 wp.rect[i] = resultRect[g][i];
01412 _cluster.workpackages.push_back(wp);
01413
01414
01415
01416
01417
01418 }
01419 }
01420 }
01421
01422 allWorker.clear();
01423 allWorker.reserve(worker[0].size() + worker[1].size());
01424 allWorker.assign(worker[0].begin(), worker[0].end());
01425 std::copy(worker[1].begin(), worker[1].end(),
01426 std::back_insert_iterator<std::vector<Worker> >(allWorker));
01427
01428
01429
01430
01431
01432 }
01433
01436 void BalancedMultiWindow::sortBBoxes(VPort &port,UInt32 axis,
01437 Int32 const (&rect)[4])
01438 {
01439 std::vector<BBox>::iterator bI;
01440 BBoxList *freeList;
01441 Int32 pos,from,to;
01442 Real32 constant,pixel;
01443 UInt32 otherAxis = axis^1;
01444 Int32 t,b;
01445 Real32 area;
01446
01447
01448 if(Int32(_groupOpen.size()) < rect[axis+2] + 1)
01449 _groupOpen.resize(rect[axis+2] + 1);
01450
01451
01452 if(Int32(_groupClose.size()) < rect[axis+2] + 1)
01453 _groupClose.resize(rect[axis+2] + 1);
01454
01455
01456 if(_bboxlist.size() < port.bboxes.size() * 2)
01457 _bboxlist.resize(port.bboxes.size() * 2);
01458
01459
01460 for(pos = rect[axis] ; pos <= rect[axis+2] ; ++pos)
01461 _groupOpen[pos] = _groupClose[pos] = NULL;
01462
01463 freeList = &_bboxlist.front();
01464 for(bI = port.bboxes.begin() ; bI != port.bboxes.end() ; ++bI)
01465 {
01466
01467 if(bI->rect[LEFT ] > rect[RIGHT ] ||
01468 bI->rect[BOTTOM] > rect[TOP ] ||
01469 bI->rect[RIGHT ] < rect[LEFT ] ||
01470 bI->rect[TOP ] < rect[BOTTOM])
01471 continue;
01472 from = bI->rect[axis];
01473 to = bI->rect[axis+2];
01474
01475
01476 area = ( bI->rect[2] - bI->rect[0] + 1 ) *
01477 ( bI->rect[3] - bI->rect[1] + 1 );
01478
01479
01480 if(from < rect[axis ])
01481 from = rect[axis];
01482 if(to > rect[axis+2])
01483 to = rect[axis+2];
01484
01485
01486 b = bI->rect[otherAxis];
01487 t = bI->rect[otherAxis+2];
01488 if(b < rect[otherAxis])
01489 b = rect[otherAxis];
01490 if(t > rect[otherAxis+2])
01491 t = rect[otherAxis+2];
01492
01493
01494 LoadGroup &group = _cluster.loadGroups[bI->groupId];
01495 constant = group.constant;
01496 pixel = (t-b+1) * ( group.pixel + group.ratio / area );
01497
01498
01499 freeList->next = _groupOpen[from];
01500 freeList->constant = constant;
01501 freeList->pixel = pixel;
01502 _groupOpen[from] = freeList++;
01503
01504
01505 freeList->next = _groupClose[to];
01506 freeList->constant = constant;
01507 freeList->pixel = pixel;
01508 _groupClose[to] = freeList++;
01509
01510
01511 }
01512 }
01513
01516 void BalancedMultiWindow::splitAxis(Real32 const (&load)[2],
01517 VPort &port,
01518 Int32 const (&rect)[4],
01519 int axis,
01520 Real32 (&resultLoad)[2],
01521 Int32 (&resultRect)[2][4])
01522 {
01523 Int32 from,to,cut;
01524 BBoxList *bl;
01525 Real64 leftLoad = 0;
01526 Real64 rightLoad = load[0] + load[1];
01527 Real64 openPixel=0;
01528 UInt32 otherAxis = axis^1;
01529 Real64 scaleLeft = 1 / load[0];
01530 Real64 scaleRight = 1 / load[1];
01531 Real64 lastLeft;
01532 Real64 lastRight;
01533 #if 0
01534 if(load[0] >= load[1] &&
01535 load[0] / load[1] < 1.4)
01536 scaleLeft = scaleRight = 1.0;
01537 if(load[1] >= load[0] &&
01538 load[1] / load[0] < 1.4)
01539 scaleLeft = scaleRight = 1.0;
01540 #endif
01541
01542 sortBBoxes(port,axis,rect);
01543
01544 for(from = rect[axis] ;
01545 from <= rect[axis+2] &&
01546 _groupOpen[from] == NULL &&
01547 _groupClose[from] == NULL
01548 ; ++from) ;
01549 for(to = rect[axis+2] ;
01550 to >= from &&
01551 _groupOpen[to] == NULL &&
01552 _groupClose[to] == NULL
01553 ; --to) ;
01554
01555
01556
01557 lastLeft = 0;
01558 lastRight = rightLoad;
01559 for(cut = from ; cut < to ; ++cut)
01560 {
01561
01562 bl = _groupOpen[cut];
01563 while(bl)
01564 {
01565 openPixel += bl->pixel;
01566 leftLoad += bl->constant;
01567 bl = bl->next;
01568 }
01569 leftLoad += openPixel;
01570 rightLoad -= openPixel;
01571
01572 bl = _groupClose[cut];
01573 while(bl)
01574 {
01575 openPixel -= bl->pixel;
01576 rightLoad -= bl->constant;
01577 bl = bl->next;
01578 }
01579
01580
01581
01582
01583
01584
01585
01586
01587 if(leftLoad * scaleLeft >= rightLoad * scaleRight)
01588 {
01589 break;
01590 }
01591
01592 lastLeft = leftLoad;
01593 lastRight = rightLoad;
01594 }
01595 if((osgMax(leftLoad*scaleLeft,rightLoad*scaleRight) >
01596 osgMax(lastLeft*scaleLeft,lastRight*scaleRight) &&
01597 cut > from) ||
01598 (cut > from && cut == to))
01599 {
01600 cut--;
01601 leftLoad = lastLeft;
01602 rightLoad = lastRight;
01603 }
01604
01605
01606 resultLoad[0] = leftLoad;
01607 resultRect[0][axis] = from;
01608 resultRect[0][otherAxis] = rect[otherAxis];
01609 resultRect[0][axis+2] = cut;
01610 resultRect[0][otherAxis+2] = rect[otherAxis+2];
01611
01612
01613 resultLoad[1] = rightLoad;
01614 resultRect[1][axis] = cut+1;
01615 resultRect[1][otherAxis] = rect[otherAxis];
01616 resultRect[1][axis+2] = to;
01617 resultRect[1][otherAxis+2] = rect[otherAxis+2];
01618
01619
01620 #if 0
01621 for(cut = rect[axis] ;
01622 cut <= rect[axis+2] &&
01623 _groupOpen[cut] == NULL &&
01624 _groupClose[cut] == NULL
01625 ; ++cut)
01626 resultRect[0][axis]++;
01627
01628 for(cut = rect[axis+2] ;
01629 cut >= rect[axis] &&
01630 _groupOpen[cut] == NULL &&
01631 _groupClose[cut] == NULL
01632 ; --cut)
01633 resultRect[1][axis+2]--;
01634 #endif
01635 }
01636
01637
01638
01641 void BalancedMultiWindow::renderViewport(Window *serverWindow,
01642 UInt32 id,
01643 RenderActionBase *action,
01644 UInt32 portId,
01645 Int32 const (&rect)[4])
01646 {
01647
01648 _foreignPort.id = portId;
01649 _foreignPort.serverId = id;
01650 _foreignPort.root = getPort(portId)->getRoot();
01651
01652 calculateServerPort(_foreignPort,rect);
01653
01654 serverWindow->addPort(_foreignPort.serverPort);
01655
01656 if(_foreignPort.serverPort->getPixelLeft() <=
01657 _foreignPort.serverPort->getPixelRight() &&
01658 _foreignPort.serverPort->getPixelBottom() <=
01659 _foreignPort.serverPort->getPixelTop())
01660 {
01661
01662 action->setWindow(serverWindow);
01663 _foreignPort.serverPort->render(action);
01664
01665
01666
01667
01668
01669
01670
01671
01672 action->setFrustumCulling(true);
01673 }
01674
01675
01676 serverWindow->subPortByObj(_foreignPort.serverPort);
01677 }
01678
01681
01682 void BalancedMultiWindow::clearViewports(Window *serverWindow,
01683 UInt32 id,
01684 RenderActionBase *action)
01685 {
01686 UInt32 vp;
01687 UInt32 travMask;
01688
01689
01690 if(_cluster.servers[id].viewports.size() == 0)
01691 {
01692 glViewport(0,0,
01693 serverWindow->getWidth(),
01694 serverWindow->getHeight());
01695 glClearColor(0,0,0,0);
01696
01697 }
01698
01699 for(vp=0 ; vp<_cluster.servers[id].viewports.size() ; ++vp)
01700 {
01701 VPort &port = _cluster.servers[id].viewports[vp];
01702
01703
01704 travMask = port.root->getTravMask();
01705 port.root->setTravMask(0);
01706
01707
01708 calculateServerPort(port,port.rect);
01709
01710
01711 serverWindow->addPort(port.serverPort);
01712
01713
01714 action->setWindow(serverWindow);
01715 port.serverPort->render(action);
01716
01717
01718 serverWindow->subPortByObj(port.serverPort);
01719
01720 port.root->setTravMask(travMask);
01721 }
01722 }
01723
01724
01727 void BalancedMultiWindow::storeViewport(Area &area,Viewport *vp,
01728 Int32 const (&rect)[4])
01729 {
01730 Int32 x,y,w,h;
01731 UInt32 tI=0;
01732
01733
01734
01735
01736 vp->activate();
01737
01738 area.tiles.resize(calcTileCount(rect));
01739
01740 for(y = rect[BOTTOM] ; y <= rect[TOP] ; y += MW_TILE_SIZE)
01741 {
01742 for(x = rect[LEFT] ; x <= rect[RIGHT] ; x += MW_TILE_SIZE)
01743 {
01744 w = osgMin(Int32(MW_TILE_SIZE),rect[RIGHT] - x + 1);
01745 h = osgMin(Int32(MW_TILE_SIZE),rect[TOP] - y + 1);
01746
01747 area.tiles[tI].header.x = x;
01748 area.tiles[tI].header.y = y;
01749 area.tiles[tI].header.width = w;
01750 area.tiles[tI].header.height = h;
01751 area.tiles[tI].header.last = false;
01752
01753 if(getShort())
01754 {
01755 glReadPixels(area.tiles[tI].header.x,
01756 area.tiles[tI].header.y,
01757 w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
01758 area.tiles[tI].pixel);
01759 }
01760 else
01761 {
01762 glReadPixels(area.tiles[tI].header.x,
01763 area.tiles[tI].header.y,
01764 w, h, GL_RGB, GL_UNSIGNED_BYTE,
01765 area.tiles[tI].pixel);
01766 }
01767 tI++;
01768 }
01769 }
01770 area.tiles[tI-1].header.last = true;
01771
01772 vp->deactivate();
01773 }
01774
01775
01776 void BalancedMultiWindow::drawSendAndRecv(Window *window,
01777 RenderActionBase *action,
01778 UInt32 id)
01779 {
01780 UInt16 wpId;
01781 UInt32 sendCount;
01782 GroupConnection *groupConn;
01783
01784
01785 std::vector<WorkPackage>::iterator wI;
01786 std::vector<Area>::iterator aI;
01787 std::vector<Tile>::iterator tI;
01788 Tile tile;
01789 Connection::Channel channel=0;
01790
01791 _triCount = 0;
01792 _drawTime = 0;
01793 _pixelTime = 0;
01794 _netTime = 0;
01795
01796 #ifdef CHECK
01797
01798 if(action->getStatistics() == NULL)
01799 {
01800 action->setStatistics(new StatCollector());
01801 action->getStatistics()->getElem( Drawable::statNTriangles )->getValue();
01802 }
01803 #endif
01804
01805 Connection *conn = getNetwork()->getMainConnection();
01806
01807
01808 if(window != NULL)
01809 {
01810 window->activate ();
01811 window->frameInit();
01812
01813
01814 for(wI = _cluster.workpackages.begin(), wpId=0;
01815 wI != _cluster.workpackages.end() ;
01816 ++wI, ++wpId)
01817 {
01818 if(wI->drawServer == id &&
01819 wI->sendToServer != id)
01820 {
01821
01822 _cluster.areas.resize(_cluster.areas.size()+1);
01823 _cluster.areas.back().workpackageId = wpId;
01824 renderViewport(window,
01825 wI->sendToServer,
01826 action,
01827 wI->viewportId,
01828 wI->rect);
01829 glFinish();
01830 _pixelTime -= getSystemTime();
01831 storeViewport (_cluster.areas.back(),
01832 getPort(wI->viewportId),
01833 wI->rect);
01834 _pixelTime += getSystemTime();
01835
01836 #ifdef CHECK
01837 _triCount += (UInt32)action->getStatistics()->getElem( Drawable::statNTriangles )->getValue();
01838 _drawTime += action->getStatistics()->getElem( RenderAction::statDrawTime )->getValue();
01839 #endif
01840 }
01841 }
01842
01843
01844 clearViewports(window,id,action);
01845
01846
01847 for(wI = _cluster.workpackages.begin() ;
01848 wI != _cluster.workpackages.end() ;
01849 ++wI)
01850 {
01851 if(wI->drawServer == id &&
01852 wI->sendToServer == id)
01853 {
01854
01855 renderViewport(window,
01856 id,
01857 action,
01858 wI->viewportId,
01859 wI->rect);
01860 #ifdef CHECK
01861 _triCount += (UInt32)action->getStatistics()->getElem( Drawable::statNTriangles )->getValue();
01862 _drawTime += action->getStatistics()->getElem( RenderAction::statDrawTime )->getValue();
01863 #endif
01864 }
01865 }
01866
01867 sendCount = _cluster.areas.size();
01868 groupConn = getNetwork()->getGroupConnection(id);
01869 while(sendCount)
01870 {
01871 groupConn->selectChannel();
01872 groupConn->getValue(wpId);
01873 for(aI = _cluster.areas.begin() ; aI != _cluster.areas.end() ; ++aI)
01874 {
01875 if(wpId == aI->workpackageId)
01876 {
01877 conn = getNetwork()->getConnection(_cluster.workpackages[wpId].sendToServer);
01878 for(tI = aI->tiles.begin() ; tI != aI->tiles.end() ; ++tI)
01879 {
01880 if(getShort())
01881 conn->put(&(*tI),UInt32(osgAbs(tI->header.width)) * tI->header.height * 2 + sizeof(Tile::Header));
01882 else
01883 conn->put(&(*tI),UInt32(osgAbs(tI->header.width)) * tI->header.height * 3 + sizeof(Tile::Header));
01884 }
01885 conn->flush();
01886 sendCount--;
01887 break;
01888 }
01889 }
01890 }
01891
01892 _netTime -= getSystemTime();
01893
01894 glPushMatrix();
01895 glLoadIdentity();
01896 glMatrixMode(GL_PROJECTION);
01897 glPushMatrix();
01898 glLoadIdentity();
01899 gluOrtho2D(0, window->getWidth(), 0, window->getHeight());
01900 glDisable(GL_DEPTH_TEST);
01901 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01902 groupConn = getNetwork()->getGroupConnection(id);
01903 wpId = 0;
01904 wI = _cluster.workpackages.begin();
01905 while(wI != _cluster.workpackages.end() &&
01906 (wI->drawServer == id || wI->sendToServer != id))
01907 {
01908 ++wI; ++wpId;
01909 }
01910 if(wI != _cluster.workpackages.end())
01911 {
01912 conn = getNetwork()->getConnection(wI->drawServer);
01913 conn->putValue(wpId);
01914 conn->flush();
01915 }
01916 while(wI != _cluster.workpackages.end())
01917 {
01918 Viewport *vp = getPort(wI->viewportId);
01919
01920 vp->activate();
01921
01922
01923 glViewport(0, 0,
01924 window->getWidth(), window->getHeight());
01925 glDisable(GL_SCISSOR_TEST);
01926
01927 channel = groupConn->selectChannel();
01928 do
01929 {
01930 groupConn->get(&tile,sizeof(Tile::Header));
01931 if(tile.header.last)
01932 {
01933 ++wI; ++wpId;
01934
01935 while(wI != _cluster.workpackages.end() &&
01936 (wI->drawServer == id || wI->sendToServer != id))
01937 {
01938 ++wI; ++wpId;
01939 }
01940 if(wI != _cluster.workpackages.end())
01941 {
01942 conn = getNetwork()->getConnection(wI->drawServer);
01943 conn->putValue(wpId);
01944 conn->flush();
01945 }
01946 }
01947 if(getShort())
01948 groupConn->get(&tile.pixel,tile.header.width*tile.header.height*2);
01949 else
01950 groupConn->get(&tile.pixel,tile.header.width*tile.header.height*3);
01951 _netTime += getSystemTime();
01952 _pixelTime -= getSystemTime();
01953 glRasterPos2i (tile.header.x,tile.header.y);
01954 if(getShort())
01955 glDrawPixels(tile.header.width,tile.header.height,
01956 GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
01957 &(tile.pixel[0]));
01958 else
01959 glDrawPixels(tile.header.width,tile.header.height,
01960 GL_RGB, GL_UNSIGNED_BYTE,
01961 &(tile.pixel[0]));
01962
01963 if(getShowBalancing())
01964 {
01965 #if 1
01966 static Real32 col[16][3] = {
01967 {1,0,0},
01968 {0,1,0},
01969 {0,0,1},
01970 {1,1,0},
01971 {1,0,1},
01972 {0,1,1},
01973 {1,1,1},
01974 {1,.5,0},
01975 {.5,0,0},
01976 {0,.5,0},
01977 {0,0,.5},
01978 {.5,.5,0},
01979 {.5,0,1},
01980 {0,.5,1},
01981 {1,1,.5},
01982 {.5,.5,0}
01983 };
01984 glEnable(GL_BLEND);
01985 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
01986 glBegin(GL_QUADS);
01987 glColor4f(col[channel%16][0],
01988 col[channel%16][1],
01989 col[channel%16][2],
01990 .3f);
01991 glVertex2i(tile.header.x , tile.header.y);
01992 glVertex2i(tile.header.x , tile.header.y+tile.header.height);
01993 glVertex2i(tile.header.x+tile.header.width, tile.header.y+tile.header.height);
01994 glVertex2i(tile.header.x+tile.header.width, tile.header.y);
01995 glEnd();
01996 glDisable(GL_BLEND);
01997 #endif
01998 }
01999 _pixelTime += getSystemTime();
02000 _netTime -= getSystemTime();
02001 }
02002 while(!tile.header.last);
02003
02004 vp->deactivate();
02005
02006
02007
02008
02009
02010 }
02011 glPopMatrix();
02012 glMatrixMode(GL_MODELVIEW);
02013 glPopMatrix();
02014 glEnable(GL_DEPTH_TEST);
02015 }
02016 _netTime += getSystemTime();
02017 }
02018
02021 void BalancedMultiWindow::preloadCache(Window *window,
02022 RenderActionBase *action)
02023 {
02024 Node *root = NULL;
02025 UInt32 v;
02026
02027 if(!_preloadCache)
02028 return;
02029
02030 _preloadCache = false;
02031
02032 window->activate();
02033 window->frameInit();
02034
02035
02036 for(v = 0 ; v < getMFPort()->size() ; ++v )
02037 {
02038 Viewport *viewport = getPort(v);
02039
02040 if(root == viewport->getRoot())
02041 continue;
02042
02043 root = viewport->getRoot();
02044
02045 if(root == NULL)
02046 continue;
02047
02048 root->updateVolume();
02049 window->activate();
02050 window->frameInit();
02051
02052
02053 NodeUnrecPtr cartN = Node::create();
02054 TransformUnrecPtr cart = Transform::create();
02055
02056 cartN->setCore(cart);
02057
02058 root->addChild(cartN);
02059
02060
02061 PerspectiveCameraUnrecPtr cam = PerspectiveCamera::create();
02062
02063 cam->setBeacon( cartN );
02064 cam->setFov ( osgDegree2Rad( 60 ) );
02065
02066
02067 SolidBackgroundUnrecPtr bkgnd = SolidBackground::create();
02068
02069
02070 ViewportUnrecPtr vp = Viewport::create();
02071
02072 vp->setCamera( cam );
02073 vp->setBackground( bkgnd );
02074 vp->setRoot( root );
02075 vp->setSize( 0,0, 1,1 );
02076
02077
02078 window->addPort(vp);
02079
02080
02081 Vec3f min,max;
02082 root->getVolume().getBounds( min, max );
02083 Vec3f d = max - min;
02084 Real32 dist = osgMax(d[0],d[1]) / (2 * osgTan(cam->getFov() / 2.f));
02085 Vec3f up(0,1,0);
02086 Pnt3f at((min[0] + max[0]) * .5f,
02087 (min[1] + max[1]) * .5f,
02088 (min[2] + max[2]) * .5f);
02089 Pnt3f from=at;
02090 from[2]+=(dist*3);
02091
02092 Matrix &matrix = cart->editMatrix();
02093 MatrixLookAt(matrix, from, at, up);
02094
02095
02096 Real32 diag = osgMax(osgMax(d[0], d[1]), d[2]);
02097
02098 cam->setNear (diag / 100.f);
02099 cam->setFar (10 * dist);
02100
02101
02102 action->setWindow(window);
02103 vp->render(action);
02104
02105
02106 window->subPortByObj(vp);
02107 root->subChild(cartN);
02108 }
02109 }
02110
02111 OSG_END_NAMESPACE