1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 2007 Cedric Pinson
2  *
3  * This application is open source and may be redistributed and/or modified
4  * freely and without restriction, both in commercial and non commercial
5  * applications, as long as this copyright notice is maintained.
6  *
7  * This application is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  *
11  * Authors:
12  *  Cedric Pinson <mornifle@plopbyte.net>
13  *
14  */
15 
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #ifndef DATADIR
22 #define DATADIR "."
23 #endif // DATADIR
24 
25 #include <osg/GraphicsContext>
26 #include "RenderSurface.h"
27 #include "CameraConfig.h"
28 #include <osgDB/FileNameUtils>
29 #include <osgDB/FileUtils>
30 #include <osgDB/Registry>
31 #include <osgDB/Input>
32 #include <osgDB/Output>
33 #include <osgDB/ReadFile>
34 #include <osgDB/WriteFile>
35 #include <osg/io_utils>
36 
37 using namespace osgProducer;
buildTrait(RenderSurface & rs)38 static osg::GraphicsContext::Traits* buildTrait(RenderSurface& rs)
39 {
40     VisualChooser& vc = *rs.getVisualChooser();
41 
42     osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
43 
44     for (std::vector<VisualChooser::VisualAttribute>::iterator it = vc._visual_attributes.begin();
45         it != vc._visual_attributes.end();
46         it++)
47     {
48         switch(it->_attribute)
49         {
50             case(VisualChooser::UseGL):            break; // on by default in osgViewer
51             case(VisualChooser::BufferSize):       break; // no present mapping
52             case(VisualChooser::Level):            traits->level = it->_parameter; break;
53             case(VisualChooser::RGBA):             break; // automatically set in osgViewer
54             case(VisualChooser::DoubleBuffer):     traits->doubleBuffer = true; break;
55             case(VisualChooser::Stereo):           traits->quadBufferStereo = true; break;
56             case(VisualChooser::AuxBuffers):       break; // no present mapping
57             case(VisualChooser::RedSize):          traits->red = it->_parameter; break;
58             case(VisualChooser::GreenSize):        traits->green = it->_parameter; break;
59             case(VisualChooser::BlueSize):         traits->blue = it->_parameter; break;
60             case(VisualChooser::AlphaSize):        traits->alpha = it->_parameter; break;
61             case(VisualChooser::DepthSize):        traits->depth = it->_parameter; break;
62             case(VisualChooser::StencilSize):      traits->stencil = it->_parameter; break;
63             case(VisualChooser::AccumRedSize):     break; // no present mapping
64             case(VisualChooser::AccumGreenSize):   break; // no present mapping
65             case(VisualChooser::AccumBlueSize):    break; // no present mapping
66             case(VisualChooser::AccumAlphaSize):   break; // no present mapping
67             case(VisualChooser::Samples):          traits->samples = it->_parameter; break;
68             case(VisualChooser::SampleBuffers):    traits->sampleBuffers = 1; break;
69         }
70     }
71 
72     OSG_INFO<<"ReaderWriterCFG buildTrait traits->depth="<<traits->depth<<std::endl;
73     OSG_INFO<<"ReaderWriterCFG buildTrait traits->samples="<<traits->samples<<std::endl;
74     OSG_INFO<<"ReaderWriterCFG buildTrait traits->sampleBuffers="<<traits->sampleBuffers<<std::endl;
75 
76 
77     traits->hostName = rs.getHostName();
78     traits->displayNum = rs.getDisplayNum();
79     traits->screenNum = rs.getScreenNum();
80     traits->windowName = rs.getWindowName();
81     traits->x = rs.getWindowOriginX();
82     traits->y = rs.getWindowOriginY();
83     traits->width = rs.getWindowWidth();
84     traits->height = rs.getWindowHeight();
85     traits->windowDecoration = rs.usesBorder();
86     traits->sharedContext = 0;
87     traits->pbuffer = (rs.getDrawableType()==osgProducer::RenderSurface::DrawableType_PBuffer);
88 
89     traits->overrideRedirect = rs.usesOverrideRedirect();
90 
91     return traits;
92  }
93 
load(const std::string & file,const osgDB::ReaderWriter::Options * option)94 static osgViewer::View* load(const std::string& file, const osgDB::ReaderWriter::Options* option)
95 {
96     osg::ref_ptr<CameraConfig> config = new CameraConfig;
97     //std::cout << "Parse file " << file << std::endl;
98     config->parseFile(file);
99 
100     RenderSurface* rs = 0;
101     Camera* cm = 0;
102     std::map<RenderSurface*,osg::ref_ptr<osg::GraphicsContext> > surfaces;
103     osg::ref_ptr<osgViewer::View> _view = new osgViewer::View;
104 
105     if (config->getNumberOfCameras()==1)
106     {
107         cm = config->getCamera(0);
108         rs = cm->getRenderSurface();
109         if (rs->getDrawableType() != osgProducer::RenderSurface::DrawableType_Window) return 0;
110 
111         osg::ref_ptr<const osg::GraphicsContext::Traits> traits;
112         osg::ref_ptr<osg::GraphicsContext> gc;
113         if (surfaces.find(rs) != surfaces.end())
114         {
115             gc = surfaces[rs];
116             traits = gc.valid() ? gc->getTraits() : 0;
117         }
118         else
119         {
120             osg::GraphicsContext::Traits* newtraits = buildTrait(*rs);
121 
122 #if 0
123             osg::GraphicsContext::ScreenIdentifier si;
124             si.readDISPLAY();
125 
126             if (si.displayNum>=0) newtraits->displayNum = si.displayNum;
127             if (si.screenNum>=0) newtraits->screenNum = si.screenNum;
128 #endif
129 
130             gc = osg::GraphicsContext::createGraphicsContext(newtraits);
131 
132             surfaces[rs] = gc.get();
133             traits = gc.valid() ? gc->getTraits() : 0;
134         }
135 
136         // std::cout << rs->getWindowName() << " " << rs->getWindowOriginX() << " " << rs->getWindowOriginY() << " " << rs->getWindowWidth() << " " << rs->getWindowHeight() << std::endl;
137 
138         if (gc.valid())
139         {
140             OSG_INFO<<"  GraphicsWindow has been created successfully."<<std::endl;
141 
142             osg::ref_ptr<osg::Camera> camera = _view->getCamera();
143 
144             camera->setGraphicsContext(gc.get());
145 
146             int x,y;
147             unsigned int width,height;
148             cm->applyLens();
149             cm->getProjectionRectangle(x, y, width, height);
150             camera->setViewport(new osg::Viewport(x, y, width, height));
151 
152             GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
153             camera->setDrawBuffer(buffer);
154             camera->setReadBuffer(buffer);
155             camera->setProjectionMatrix(osg::Matrixd(cm->getProjectionMatrix()));
156             camera->setViewMatrix(osg::Matrixd(cm->getPositionAndAttitudeMatrix()));
157 
158             #if 0
159             std::cout << "Matrix Projection " << projection << std::endl;
160             std::cout << "Matrix Projection master " << _view->getCamera()->getProjectionMatrix() << std::endl;
161             // will work only if it's a post multyply in the producer camera
162             std::cout << "Matrix View " << view << std::endl;
163             std::cout << _view->getCamera()->getProjectionMatrix() * offsetProjection << std::endl;
164             #endif
165         }
166         else
167         {
168             OSG_INFO<<"  GraphicsWindow has not been created successfully."<<std::endl;
169             return 0;
170         }
171 
172     }
173     else
174     {
175         for (int i = 0; i < (int)config->getNumberOfCameras(); i++)
176         {
177             cm = config->getCamera(i);
178             rs = cm->getRenderSurface();
179             if (rs->getDrawableType() != osgProducer::RenderSurface::DrawableType_Window)
180                 continue;
181 
182             osg::ref_ptr<const osg::GraphicsContext::Traits> traits;
183             osg::ref_ptr<osg::GraphicsContext> gc;
184             if (surfaces.find(rs) != surfaces.end())
185             {
186                 gc = surfaces[rs];
187                 traits = gc.valid() ? gc->getTraits() : 0;
188             }
189             else
190             {
191                 osg::GraphicsContext::Traits* newtraits = buildTrait(*rs);
192 
193     #if 0
194                 osg::GraphicsContext::ScreenIdentifier si;
195                 si.readDISPLAY();
196 
197                 if (si.displayNum>=0) newtraits->displayNum = si.displayNum;
198                 if (si.screenNum>=0) newtraits->screenNum = si.screenNum;
199     #endif
200 
201                 gc = osg::GraphicsContext::createGraphicsContext(newtraits);
202 
203                 surfaces[rs] = gc.get();
204                 traits = gc.valid() ? gc->getTraits() : 0;
205             }
206 
207             // std::cout << rs->getWindowName() << " " << rs->getWindowOriginX() << " " << rs->getWindowOriginY() << " " << rs->getWindowWidth() << " " << rs->getWindowHeight() << std::endl;
208 
209             if (gc.valid())
210             {
211                 OSG_INFO<<"  GraphicsWindow has been created successfully."<<std::endl;
212 
213                 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
214                 camera->setGraphicsContext(gc.get());
215 
216 
217                 int x,y;
218                 unsigned int width,height;
219                 cm->applyLens();
220                 cm->getProjectionRectangle(x, y, width, height);
221                 camera->setViewport(new osg::Viewport(x, y, width, height));
222 
223                 GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
224                 camera->setDrawBuffer(buffer);
225                 camera->setReadBuffer(buffer);
226 
227                 osg::Matrix projection(cm->getProjectionMatrix());
228 
229                 osg::Matrix offset = osg::Matrix::identity();
230                 cm->setViewByMatrix(offset);
231                 osg::Matrix view = osg::Matrix(cm->getPositionAndAttitudeMatrix());
232 
233                 // setup projection from parent
234                 osg::Matrix offsetProjection = osg::Matrix::inverse(_view->getCamera()->getProjectionMatrix()) * projection;
235                 _view->addSlave(camera.get(), offsetProjection, view);
236 
237                 #if 0
238                 std::cout << "Matrix Projection " << projection << std::endl;
239                 std::cout << "Matrix Projection master " << _view->getCamera()->getProjectionMatrix() << std::endl;
240                 // will work only if it's a post multyply in the producer camera
241                 std::cout << "Matrix View " << view << std::endl;
242                 std::cout << _view->getCamera()->getProjectionMatrix() * offsetProjection << std::endl;
243                 #endif
244             }
245             else
246             {
247                 OSG_INFO<<"  GraphicsWindow has not been created successfully."<<std::endl;
248                 return 0;
249             }
250         }
251     }
252 
253     // std::cout << "done" << std::endl;
254     return _view.release();
255 }
256 
257 //
258 // OSG interface to read/write from/to a file.
259 //
260 class ReaderWriterProducerCFG : public osgDB::ReaderWriter
261 {
262 public:
263 
ReaderWriterProducerCFG()264     ReaderWriterProducerCFG()
265     {
266         supportsExtension("cfg","Producer camera configuration file");
267     }
268 
className()269     virtual const char* className() { return "Producer cfg object reader"; }
270 
271 
readObject(const std::string & fileName,const Options * options=NULL) const272     virtual ReadResult readObject(const std::string& fileName, const Options* options = NULL) const
273     {
274         std::string ext = osgDB::getLowerCaseFileExtension(fileName);
275         if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
276 
277         osgDB::FilePathList* filePathList = 0;
278         if(options)
279         {
280             filePathList = const_cast<osgDB::FilePathList*>(&(options->getDatabasePathList()));
281             filePathList->push_back(DATADIR);
282         }
283 
284         std::string path = osgDB::findDataFile(fileName);
285         if(path.empty()) return ReadResult::FILE_NOT_FOUND;
286 
287         ReadResult result;
288         osg::ref_ptr<osg::View> view = load(path, options);
289         if(! view.valid())
290             result = ReadResult("Error: could not load " + path);
291         else
292             result = ReadResult(view.get());
293 
294         if(options && filePathList)
295             filePathList->pop_back();
296 
297         return result;
298     }
299 
300 };
301 
302 
303 REGISTER_OSGPLUGIN(cfg, ReaderWriterProducerCFG)
304