void MultiDisplayWindow::serverRender(WindowPtr serverWindow, UInt32 id, DrawActionBase *action ) { TileCameraDecoratorPtr deco; ViewportPtr serverPort; ViewportPtr clientPort; StereoBufferViewportPtr clientStereoPort; UInt32 sv,cv; Int32 l,r,t,b; Int32 cleft,cright,ctop,cbottom; // sync, otherwise viewports will be out of date if(!getHServers()) { setHServers(getServers().size()); } if(!getVServers()) { setVServers(1); } UInt32 row =id/getHServers(); UInt32 column=id%getHServers(); // calculate width and height from local width and height UInt32 width = serverWindow->getWidth() ; UInt32 height = serverWindow->getHeight(); if(getWidth()==0) { setWidth( width*getHServers() ); } if(getHeight()==0) { setHeight( height*getVServers() ); } Int32 left = column * width - column * getXOverlap(); Int32 bottom = row * height - row * getYOverlap(); Int32 right = left + width - 1; Int32 top = bottom + height - 1; Real64 scaleCWidth = ((width - getXOverlap()) * (getHServers() - 1) + width) / (float)getWidth(); Real64 scaleCHeight = ((height - getYOverlap())* (getVServers() - 1) + height)/ (float)getHeight(); bool isVirtualPort = false; // duplicate viewports for(cv = 0, sv = 0; cv < getPort().size(); ++cv) { clientPort = getPort()[cv]; #if 0 isVirtualPort = clientPort->getType().isDerivedFrom(FBOViewport::getClassType()); if(isVirtualPort) { // TODO -- seems wrong to render this on all servers, though rendering // then transmitting the texture doesn't seem like a good idea either. if(serverWindow->getPort().size() <= sv) { serverPort = ViewportPtr::dcast(clientPort->shallowCopy()); beginEditCP(serverWindow); serverWindow->addPort(serverPort); endEditCP(serverWindow); } else { serverPort = serverWindow->getPort()[sv]; if(serverWindow->getPort()[sv]->getType() != clientPort->getType()) { // there is a viewport with the wrong type subRefCP(serverWindow->getPort()[sv]); serverPort = ViewportPtr::dcast(clientPort->shallowCopy()); beginEditCP(serverWindow); { serverWindow->getPort()[sv] = serverPort; } endEditCP(serverWindow); } } // update changed viewport fields updateViewport(serverPort,clientPort); } else #endif { clientStereoPort = dynamic_cast<StereoBufferViewportPtr>(clientPort); cleft = (Int32)(clientPort->getPixelLeft() * scaleCWidth) ; cbottom = (Int32)(clientPort->getPixelBottom() * scaleCHeight) ; cright = (Int32)((clientPort->getPixelRight()+1) * scaleCWidth) -1; ctop = (Int32)((clientPort->getPixelTop()+1) * scaleCHeight)-1; if(cright < left || cleft > right || ctop < bottom || cbottom > top ) { // invisible on this server screen continue; } // calculate overlapping viewport l = osgMax(cleft ,left ) - left; b = osgMax(cbottom,bottom) - bottom; r = osgMin(cright ,right ) - left; t = osgMin(ctop ,top ) - bottom; if(serverWindow->getPort().size() <= sv) { serverPort = dynamic_cast<ViewportPtr>(clientPort->shallowCopy()); deco = TileCameraDecorator::create(); serverWindow->addPort(serverPort); serverPort->setCamera(deco); } else { serverPort = serverWindow->getPort()[sv]; deco = dynamic_cast<TileCameraDecoratorPtr>( serverPort->getCamera()); if(serverWindow->getPort()[sv]->getType() != clientPort->getType()) { // there is a viewport with the wrong type serverPort = dynamic_cast<ViewportPtr>(clientPort->shallowCopy()); serverWindow->replacePort(sv, serverPort);//[sv] = serverPort; serverPort->setCamera(deco); } else { deco = dynamic_cast<TileCameraDecoratorPtr>( serverPort->getCamera()); } } // update changed viewport fields updateViewport(serverPort,clientPort); // set viewport size serverPort->setSize(Real32(l),Real32(b),Real32(r),Real32(t)); // use pixel even if pixel = 1 if(serverPort->getLeft() == 1.0) serverPort->setLeft(1.0001); if(serverPort->getRight() == 1.0) serverPort->setRight(1.0001); if(serverPort->getTop() == 1.0) serverPort->setTop(1.0001); if(serverPort->getBottom() == 1.0) serverPort->setBottom(1.0001); // calculate tile parameters deco->setFullWidth ( cright-cleft ); deco->setFullHeight( ctop-cbottom ); deco->setSize( ( l+left-cleft ) / (float)( cright-cleft ), ( b+bottom-cbottom ) / (float)( ctop-cbottom ), ( r+left-cleft ) / (float)( cright-cleft ), ( t+bottom-cbottom ) / (float)( ctop-cbottom ) ); deco->setDecoratee( clientPort->getCamera() ); } sv++; } // remove unused ports while(serverWindow->getPort().size()>sv) { serverWindow->subPort(sv); } Inherited::serverRender(serverWindow,id,action); }
/*! update all changed viewport field from the client port */ void MultiDisplayWindow::updateViewport(ViewportPtr &serverPort, ViewportPtr &clientPort) { bool equal, found; // Compare the pointers. if(serverPort == clientPort) return; if(serverPort == NullFC || clientPort == NullFC) return; if(serverPort->getType() != serverPort->getType()) return; const FieldContainerType &type = serverPort->getType(); UInt32 fcount = osgMin(serverPort->getType().getNumFieldDescs(), clientPort->getType().getNumFieldDescs()); BitVector ffilter = RemoteAspect::getFieldFilter(type.getId()); for(UInt32 i = 1; i <= fcount; ++i) { const FieldDescription* fdesc = type.getFieldDescription(i); // ignore attachments if(strcmp(fdesc->getCName(), "parent") == 0 || strcmp(fdesc->getCName(), "camera") == 0) continue; BitVector mask = fdesc->getFieldMask(); // don't update filtered fields if(ffilter & mask) continue; Field *dst_field = serverPort->getField(i); Field *src_field = clientPort->getField(i); const FieldType &dst_ftype = dst_field->getType(); const FieldType &src_ftype = src_field->getType(); if(dst_ftype != src_ftype) continue; equal = true; found = false; if(strstr(dst_ftype.getCName(), "Ptr") == NULL) { // This is very slow with multi fields!!!! std::string av, bv; dst_field->getValueByStr(av); src_field->getValueByStr(bv); if(av != bv) equal = false; } else { if(dst_field->getCardinality() == FieldType::SINGLE_FIELD) { if((static_cast<SFFieldContainerPtr *>(dst_field)->getValue() != static_cast<SFFieldContainerPtr *>(src_field)->getValue())) equal = false; } else if(dst_field->getCardinality() == FieldType::MULTI_FIELD) { UInt32 j, cn = static_cast<MFFieldContainerPtr*>(src_field)->size(), sn = static_cast<MFFieldContainerPtr*>(src_field)->size(); if (strcmp(fdesc->getCName(), "foregrounds") == 0) { MFForegroundPtr sFgndBag; MFForegroundPtr::const_iterator sFgndIt, cFgndIt; DisplayFilterForegroundPtr filterFgnd = NullFC; sFgndIt = serverPort->getMFForegrounds()->begin(); cFgndIt = clientPort->getMFForegrounds()->begin(); while (sFgndIt != serverPort->getMFForegrounds()->end()) { filterFgnd = DisplayFilterForegroundPtr::dcast(*sFgndIt); if (filterFgnd != NullFC && !filterFgnd->getServer().empty()) found = true; // loaded filters found else sFgndBag.push_back(*sFgndIt); ++sFgndIt; } if (sFgndBag.size() != clientPort->getMFForegrounds()->size()) { equal = false; } else { sFgndIt = sFgndBag.begin(); while (sFgndIt != sFgndBag.end() && cFgndIt != clientPort->getMFForegrounds()->end() && *sFgndIt == *cFgndIt) { ++sFgndIt; ++cFgndIt; } if (sFgndIt != sFgndBag.end() || cFgndIt != clientPort->getMFForegrounds()->end()) equal = false; } } else { if(static_cast<MFFieldContainerPtr*>(dst_field)->size() != static_cast<MFFieldContainerPtr*>(src_field)->size()) { equal = false; } else { for(j=0;j < static_cast<MFFieldContainerPtr*>(dst_field)->size();++j) { if(((*(static_cast<MFFieldContainerPtr *>(dst_field)))[j] != (*(static_cast<MFFieldContainerPtr *>(src_field)))[j])) equal = false; } } } } } if(equal == false) { beginEditCP(serverPort, mask); dst_field->setAbstrValue(*src_field); endEditCP(serverPort, mask); if (found) { ClusterWindowPtr ptr(this); beginEditCP(ptr, DirtyFieldMask); setDirty(true); endEditCP(ptr, DirtyFieldMask); } } } }