1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGViewport.h"
47 #include "OSGStereoBufferViewport.h"
48 #include "OSGGeometry.h"
49 #include "OSGGeoPositionsFields.h"
51 #include "OSGCamera.h"
52 #include "OSGProxyGroup.h"
53 #include "OSGMaterialGroup.h"
54 #include "OSGRemoteAspect.h"
55 #include "OSGImageComposer.h"
56 #include "OSGStatisticsForeground.h"
57 #include "OSGClusterNetwork.h"
58 #include "OSGDrawEnv.h"
59 #include "OSGRenderActionBase.h"
60 #include "OSGMaterial.h"
62 #include "OSGSortLastWindow.h"
66 /*! \class OSG::SortLastWindow
67 Cluster rendering configuration for sort first image composition
70 /*----------------------------- static grouping functions -----------------*/
72 void SortLastWindow::buildGroups(void)
75 DrawableListT drawables
;
76 UInt32 groupCount
= 0;
79 // check for new nodes.
80 FieldContainerFactoryBase
*fcFactory
= FieldContainerFactory::the();
82 FieldContainer
*fcPtr
= NULL
;
84 ChangeList::ChangedStoreConstIt createdI
;
86 ChangeList
*changeList
= OSG::Thread::getCurrentChangeList();
88 for(createdI
= changeList
->beginCreated();
89 createdI
!= changeList
->endCreated();
92 UInt32 uiId
= (*createdI
)->uiContainerId
;
94 fcPtr
= fcFactory
->getContainer(uiId
);
96 if(fcPtr
!= NULL
&& dynamic_cast<Node
*>(fcPtr
) != NULL
)
100 // is rebuild neccessary ?
101 if(!rebuild
&& getMFGroupNodes()->size())
104 groupCount
= getMFServers()->size32();
106 if(getComposer() != NULL
)
108 groupCount
= getComposer()->getUsableServers();
109 if(getComposer()->getClientRendering())
113 // build groups for all viewports
116 editMFGroupLengths()->clear();
118 for(v
= 0; v
< getMFPort()->size(); ++v
)
120 Viewport
*vp
= getPort(v
);
121 Node
*root
= vp
->getRoot();
125 collectDrawables(root
, drawables
);
128 splitDrawables(drawables
, groupCount
, false);
132 /*----------------------------- server methods ----------------------------*/
136 void SortLastWindow::serverInit(Window
*serverWindow
,
139 // create default composer
140 if(getComposer() == NULL
)
143 FieldContainerPtr fcPtr =
144 FieldContainerFactory::the()->createFieldContainer("BinarySwapComposer");
145 setComposer(ImageComposerPtr::dcast(fcPtr));
149 if(getComposer() != NULL
)
152 ClusterWindow
*clusterWindow
= this;
154 getComposer()->setup(false,
159 getComposer()->open();
163 /*! update server window
166 #ifdef OSG_OLD_RENDER_ACTION
167 void SortLastWindow::serverRender(Window
*serverWindow
,
169 DrawActionBase
*action
)
171 Viewport
*serverPort
= NULL
;
172 Viewport
*clientPort
= NULL
;
175 UInt32 regionStart
= 0;
177 // duplicate viewports
178 for(cv
= 0, sv
= 0; cv
< getPort().size(); ++cv
)
180 clientPort
= getPort()[cv
];
182 if(serverWindow
->getPort().size() <= sv
)
185 serverPort
= Viewport::create();
187 serverWindow
->addPort(serverPort
);
191 serverPort
= serverWindow
->getPort()[sv
];
196 if(getWidth() && getHeight())
198 serverPort
->setSize(clientPort
->getPixelLeft (),
199 clientPort
->getPixelBottom(),
200 clientPort
->getPixelRight (),
201 clientPort
->getPixelTop ());
205 serverPort
->setSize(0,0,0,0);
208 serverPort
->setCamera (clientPort
->getCamera ());
209 serverPort
->setRoot (clientPort
->getRoot ());
210 serverPort
->setBackground(clientPort
->getBackground());
212 // ignore statistics foreground
213 serverPort
->clearForegrounds();
215 for(UInt32 f
= 0 ; f
< serverPort
->getForegrounds().size(); ++f
)
217 Foreground
*fg
= clientPort
->getForegrounds()[f
];
219 StatisticsForeground
*sfg
=
220 dynamic_cast<StatisticsForeground
*>(fg
);
224 serverPort
->addForeground(fg
);
228 serverPort
->setTravMask(clientPort
->getTravMask());
233 // remove unused ports
234 while(serverWindow
->getPort().size() > sv
)
236 serverWindow
->subPort(sv
);
239 // setup visible nodes
242 // render the viewports
243 serverWindow
->activate();
244 serverWindow
->frameInit();
246 action
->setWindow(serverWindow
);
248 if(getComposer() != NULL
)
249 getComposer()->startFrame();
251 for(sv
= 0; sv
< serverWindow
->getPort().size(); ++sv
)
253 Viewport
*vp
= serverWindow
->getPort()[sv
];
254 Node
*root
= vp
->getRoot();
256 if(getComposer() != NULL
)
257 getComposer()->startViewport(vp
);
262 // compose single viewport
263 if(getComposer() != NULL
)
264 getComposer()->composeViewport(vp
);
267 // compose whole window
268 if(getComposer() != NULL
)
269 getComposer()->composeWindow();
273 void SortLastWindow::serverRender(Window
*serverWindow
,
275 RenderActionBase
*action
)
277 ViewportUnrecPtr serverPort
= NULL
;
278 Viewport
*clientPort
= NULL
;
282 // duplicate viewports
283 for(cv
= 0, sv
= 0; cv
< getMFPort()->size(); ++cv
)
285 clientPort
= getPort(cv
);
287 if(serverWindow
->getMFPort()->size() <= sv
)
290 serverPort
= Viewport::create();
292 serverWindow
->addPort(serverPort
);
296 serverPort
= serverWindow
->getPort(sv
);
301 if(getWidth() && getHeight())
303 serverPort
->setSize(clientPort
->calcPixelLeft (),
304 clientPort
->calcPixelBottom(),
305 clientPort
->calcPixelRight (),
306 clientPort
->calcPixelTop ());
310 serverPort
->setSize(0,0,0,0);
313 serverPort
->setCamera (clientPort
->getCamera ());
314 serverPort
->setRoot (clientPort
->getRoot ());
315 serverPort
->setBackground(clientPort
->getBackground());
317 // ignore statistics foreground
318 serverPort
->clearForegrounds();
320 for(UInt32 f
= 0 ; f
< serverPort
->getMFForegrounds()->size(); ++f
)
322 Foreground
*fg
= clientPort
->getForegrounds(f
);
324 StatisticsForeground
*sfg
=
325 dynamic_cast<StatisticsForeground
*>(fg
);
329 serverPort
->addForeground(fg
);
333 serverPort
->setTravMask(clientPort
->getTravMask());
338 // remove unused ports
339 while(serverWindow
->getMFPort()->size() > sv
)
341 serverWindow
->subPort(sv
);
344 // setup visible nodes
347 // render the viewports
348 serverWindow
->activate();
349 serverWindow
->frameInit();
351 action
->setWindow(serverWindow
);
353 if(getComposer() != NULL
)
354 getComposer()->startFrame();
356 for(sv
= 0; sv
< serverWindow
->getMFPort()->size(); ++sv
)
358 Viewport
*vp
= serverWindow
->getPort(sv
);
360 if(getComposer() != NULL
)
361 getComposer()->startViewport(vp
);
366 // compose single viewport
367 if(getComposer() != NULL
)
368 getComposer()->composeViewport(vp
);
371 // compose whole window
372 if(getComposer() != NULL
)
373 getComposer()->composeWindow();
378 void SortLastWindow::serverSwap(Window
*window
,
381 if(getComposer() == NULL
)
383 Connection
*connection
= getNetwork()->getMainConnection();
384 // tell client that we are finish
385 connection
->signal();
389 Inherited::serverSwap(window
,id
);
392 /*----------------------------- client methods ----------------------------*/
394 /*! read server cababilities
396 void SortLastWindow::clientInit( void )
398 getNetwork()->getAspect()->addFieldFilter(Node::getClassType().getId(),
399 Node::VolumeFieldMask
);
400 getNetwork()->getAspect()->addFieldFilter(Node::getClassType().getId(),
401 Node::TravMaskFieldMask
);
403 // create default composer
404 if(getComposer() == NULL
)
407 FieldContainerPtr fcPtr =
408 FieldContainerFactory::the()->createFieldContainer("BinarySwapComposer");
409 setComposer(ImageComposerPtr::dcast(fcPtr));
412 if(getComposer() != NULL
)
414 SortLastWindow
*clusterWindow(this);
415 getComposer()->setup(true,
416 getMFServers()->size32(),
419 getComposer()->open();
425 /*! client frame init
427 void SortLastWindow::clientPreSync( void )
429 if(getClientWindow() != NULL
)
431 UInt32 width
=getClientWindow()->getWidth();
432 UInt32 height
=getClientWindow()->getHeight();
437 if(width
!= getWidth() ||
438 height
!= getHeight())
440 setSize(width
,height
);
444 Inherited::clientPreSync();
446 // rebuild node groups
450 #ifdef OSG_OLD_RENDER_ACTION
453 void SortLastWindow::clientRender(DrawActionBase
*action
)
456 UInt32 groupId
= getServers().size();
459 SortLastWindow
*clusterWindow(this);
461 if(getServers().size())
463 Connection
*srcConnection
=
464 getNetwork()->getConnection(groupId
);
466 if(getClientWindow() != NULL
)
470 getClientWindow()->activate();
471 getClientWindow()->frameInit();
473 action
->setWindow(getClientWindow());
475 if(getComposer() != NULL
)
476 getComposer()->startFrame();
480 oEnv
.setWindow(action
->getWindow());
482 // render all viewports
483 for(p
= 0; p
< getPort().size() ; ++p
)
485 Viewport
*vp
=getPort()[p
];
486 if(getComposer() != NULL
)
488 getComposer()->startViewport(vp
);
490 action
->setCamera (vp
->getCamera ());
491 action
->setBackground(vp
->getBackground());
492 action
->setViewport (vp
);
493 action
->setTravMask (vp
->getTravMask ());
495 action
->apply(vp
->getRoot());
497 for(UInt16 i
=0; i
< vp
->getForegrounds().size(); i
++)
499 if(dynamic_cast<StatisticsForeground
*>(
500 vp
->getForegrounds(i
)) == NULL
)
502 vp
->getForegrounds(i
)->draw(&oEnv
, vp
);
506 getComposer()->composeViewport(vp
);
508 for(UInt16 i
=0; i
< vp
->getForegrounds().size(); i
++)
510 if(dynamic_cast<StatisticsForeground
*>(
511 vp
->getForegrounds(i
)) != NULL
)
513 vp
->getForegrounds(i
)->draw(&oEnv
, vp
);
524 // compose whole window
525 if(getComposer() != NULL
)
526 getComposer()->composeWindow();
532 void SortLastWindow::clientRender(RenderActionBase
*action
)
535 UInt32 groupId
= getMFServers()->size32();
537 if(getMFServers()->size())
539 if(getClientWindow() != NULL
)
543 getClientWindow()->activate();
544 getClientWindow()->frameInit();
546 action
->setWindow(getClientWindow());
548 if(getComposer() != NULL
)
549 getComposer()->startFrame();
553 oEnv
.setWindow(action
->getWindow());
555 // render all viewports
556 for(p
= 0; p
< getMFPort()->size() ; ++p
)
558 Viewport
*vp
=getPort(p
);
560 oEnv
.setViewportDimension(vp
->calcPixelLeft (),
561 vp
->calcPixelBottom (),
562 vp
->calcPixelRight (),
564 vp
->calcIsFullWindow());
565 if(getComposer() != NULL
)
567 getComposer()->startViewport(vp
);
569 action
->setCamera (vp
->getCamera ());
570 action
->setBackground(vp
->getBackground());
571 action
->setViewarea (vp
);
572 action
->setTravMask (vp
->getTravMask ());
574 action
->apply(vp
->getRoot());
576 for(UInt16 i
=0; i
< vp
->getMFForegrounds()->size(); i
++)
578 if(dynamic_cast<StatisticsForeground
*>(
579 vp
->getForegrounds(i
)) == NULL
)
581 vp
->getForegrounds(i
)->draw(&oEnv
);
585 getComposer()->composeViewport(vp
);
587 for(UInt16 i
=0; i
< vp
->getMFForegrounds()->size(); i
++)
589 if(dynamic_cast<StatisticsForeground
*>(
590 vp
->getForegrounds(i
)) != NULL
)
592 vp
->getForegrounds(i
)->draw(&oEnv
);
603 // compose whole window
604 if(getComposer() != NULL
)
605 getComposer()->composeWindow();
612 void SortLastWindow::clientSwap( void )
614 if(getComposer() == NULL
)
616 Connection
*connection
=getNetwork()->getMainConnection();
617 // wait for all servers to finish
620 connection
->signal();
622 Inherited::clientSwap();
625 /*----------------------- constructors & destructors ----------------------*/
627 SortLastWindow::SortLastWindow(void) :
632 SortLastWindow::SortLastWindow(const SortLastWindow
&source
) :
637 /*! close composer if there is any
639 SortLastWindow::~SortLastWindow(void)
643 /*----------------------------- class specific ----------------------------*/
645 void SortLastWindow::initMethod(InitPhase ePhase
)
647 Inherited::initMethod(ePhase
);
650 /*! changed field. Handle new groups
653 void SortLastWindow::changed(ConstFieldMaskArg whichField
,
657 if(whichField
& GroupNodesFieldMask
)
658 setGroupsChanged(true);
660 Inherited::changed(whichField
, origin
, details
);
663 void SortLastWindow::dump( UInt32
,
664 const BitVector
) const
666 SLOG
<< "Dump SortLastWindow NI" << std::endl
;
669 /*! Collext all drawable nodes
672 void SortLastWindow::collectDrawables(Node
* const node
,
673 DrawableListT
&drawables
)
675 Material
*mat
= NULL
;
676 NodeCore
*core
= node
->getCore();
680 // handle material groups
681 MaterialGroup
*matGrp
= dynamic_cast<MaterialGroup
*>(core
);
685 mat
= matGrp
->getMaterial();
687 // ignore transparent material groups
688 if(mat
!= NULL
&& mat
->isTransparent())
693 Geometry
*geo
= dynamic_cast<Geometry
*>(core
);
697 mat
= geo
->getMaterial();
698 // ignore transparent materials
700 if(mat
== NULL
|| mat
->isTransparent() == false)
702 DrawableInfo drawableInfo
;
704 drawableInfo
.node
= node
;
706 // get transformed volume
707 node
->updateVolume();
710 node
->getWorldVolume(volume
);
713 volume
.getBounds(drawableInfo
.bMin
, drawableInfo
.bMax
);
716 drawableInfo
.load
= 0;
718 GeoIntegralProperty
*indicesPtr
=
719 geo
->getIndex(Geometry::PositionsIndex
);
721 if(indicesPtr
!= NULL
)
722 drawableInfo
.load
= indicesPtr
->size();
725 drawables
.push_back(drawableInfo
);
729 // handle poxy groups
730 ProxyGroup
*proxy
= dynamic_cast<ProxyGroup
*>(core
);
734 DrawableInfo drawableInfo
;
736 drawableInfo
.node
= node
;
738 // get transformed volume
739 node
->updateVolume();
742 node
->getWorldVolume(volume
);
745 volume
.getBounds(drawableInfo
.bMin
, drawableInfo
.bMax
);
748 drawableInfo
.load
= proxy
->getIndices();
751 drawables
.push_back(drawableInfo
);
755 MFUnrecChildNodePtr::const_iterator nI
;
757 for( nI
= node
->getMFChildren()->begin();
758 nI
!= node
->getMFChildren()->end();
761 collectDrawables(*nI
, drawables
);
765 /*! Split drawables in as many groups as we have servers
766 * Try to get clustered nodes
769 void SortLastWindow::splitDrawables(DrawableListT
&src
,
777 DrawableListT::iterator dI
;
794 editMFGroupLengths()->push_back(UInt32(src
.size()));
796 for(dI
= src
.begin() ; dI
!= src
.end() ; ++dI
)
798 pushToGroupNodes(dI
->node
);
799 // srcLoad+=dI->load;
801 // printf("load:%f\n",srcLoad);
805 groups1
= groups
/ 2;
806 groups2
= groups
- groups1
;
808 // collect all load and get summed volume
809 for(dI
= src
.begin() ; dI
!= src
.end() ; ++dI
)
811 vol
.extendBy(dI
->bMin
);
812 vol
.extendBy(dI
->bMax
);
818 if(size
[0] > size
[1])
820 if(size
[0] > size
[2])
827 if(size
[1] > size
[2])
836 std::sort(src
.begin(),src
.end(), DrawableInfo::MaxXOrder());
841 std::sort(src
.begin(),src
.end(), DrawableInfo::MaxYOrder());
843 std::sort(src
.begin(),src
.end(), DrawableInfo::MaxZOrder());
850 dIBack
= UInt32(src
.size()) - 1;
853 // printf("f %d b %d\n",dIFront,dIBack);
854 if(dst2Load
< dst1Load
)
856 dst2
.push_back(src
[dIBack
]);
858 dst2Load
+= src
[dIBack
].load
*groups
/Real32(groups2
);
864 dst1
.push_back(src
[dIFront
]);
866 dst1Load
+= src
[dIFront
].load
*groups
/Real32(groups1
);
870 } while(dIFront
<= dIBack
);
873 splitDrawables(dst1
, groups1
, cut
);
874 splitDrawables(dst2
, groups2
, cut
);
877 void SortLastWindow::setupNodes(UInt32 groupId
)
885 UInt32 groupCount
= 0;
886 UInt32 usableServers
= getMFServers()->size32();
888 if(!getGroupsChanged())
891 // client and no client rendering
892 if(getMFServers()->size() == groupId
&&
893 (getComposer() == NULL
||
894 !getComposer()->getClientRendering()))
896 for(nI
= 0 ; nI
< getMFGroupNodes()->size() ; ++nI
)
898 if(getGroupNodes(nI
)->getTravMask())
900 getGroupNodes(nI
)->setTravMask(0);
901 getGroupNodes(nI
)->invalidateVolume();
908 if(getComposer() != NULL
)
909 usableServers
= getComposer()->getUsableServers();
911 // server but not usable, then invalidate all nodes
912 if((getMFServers()->size() > groupId
&& usableServers
<= groupId
))
914 for(v
= 0; v
< getMFPort()->size(); ++v
)
916 root
= getPort(v
)->getRoot();
918 root
->setTravMask(0);
919 root
->invalidateVolume();
922 setGroupsChanged(false);
926 groupCount
= usableServers
;
928 if(getComposer() != NULL
)
930 groupCount
= getComposer()->getUsableServers();
932 if(getComposer()->getClientRendering())
938 if(getMFServers()->size() == groupId
)
939 groupId
= usableServers
;
942 for(nI
= 0,gnI
= 0,gI
= 0,group
= 0 ; nI
< getMFGroupNodes()->size() ; ++nI
)
946 gnI
+= getGroupLengths(group
);
948 group
= gI
% groupCount
;
952 if(getGroupNodes(nI
)->getTravMask() !=
953 TypeTraits
<UInt32
>::getMax())
955 getGroupNodes(nI
)->setTravMask(TypeTraits
<UInt32
>::getMax());
956 getGroupNodes(nI
)->invalidateVolume();
961 if(getGroupNodes(nI
)->getTravMask())
963 getGroupNodes(nI
)->setTravMask(0);
964 getGroupNodes(nI
)->invalidateVolume();
968 getGroupNodes(nI
)->updateVolume();
971 setGroupsChanged(false);
974 /*------------------------------------------------------------------------*/
975 /* constructor / destructor */
979 SortLastWindow::DrawableInfo::DrawableInfo():
990 SortLastWindow::DrawableInfo::DrawableInfo(const DrawableInfo
&source
) :
1000 const SortLastWindow::DrawableInfo
&SortLastWindow::DrawableInfo::operator =(
1001 const DrawableInfo
&source
)
1011 /*! compare max x in bounding volume
1014 bool SortLastWindow::DrawableInfo::MaxXOrder::operator()
1015 (const DrawableInfo
&a
, const DrawableInfo
&b
)
1017 return a
.bMax
[0] < b
.bMax
[0];
1020 /*! compare max y in bounding volume
1023 bool SortLastWindow::DrawableInfo::MaxYOrder::operator()
1024 (const DrawableInfo
&a
, const DrawableInfo
&b
)
1026 return a
.bMax
[1] < b
.bMax
[1];
1029 /*! compare max z in bounding volume
1032 bool SortLastWindow::DrawableInfo::MaxZOrder::operator()
1033 (const DrawableInfo
&a
, const DrawableInfo
&b
)
1035 return a
.bMax
[2] < b
.bMax
[2];