source: experimental/distortionNG/extViewer.cpp @ 350

Last change on this file since 350 was 350, checked in by Torben Dannhauer, 12 years ago
File size: 15.0 KB
Line 
1/* osgVisual test. distortionNG, experimental.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include "extViewer.h"
20#include "distortionNG.h"
21
22#include <osg/PolygonOffset>
23#include <osg/Texture2D>
24#include <osg/TextureRectangle>
25#include <osg/TexMat>
26#include <osg/ComputeBoundsVisitor>
27#include <osg/Vec2>
28
29#include <osgDB/ReadFile>
30#include <osgDB/FileUtils>
31
32#include <osgUtil/SmoothingVisitor>
33
34#include "DistortionManipulator.h"
35
36extViewer::extViewer() : Viewer()
37{
38}
39
40extViewer::extViewer(osg::ArgumentParser& arguments) : Viewer(arguments)
41{
42        // Add help for command-line options here
43    arguments.getApplicationUsage()->addCommandLineOption("--distort","load distortion file and set up geometrical distortion for viewer. This includes blending");
44    arguments.getApplicationUsage()->addCommandLineOption("--blend","Set up viewer vor simple blending CullDrawThreadPerContext threading model for viewer.");
45
46        osgDB::Registry::instance()->addFileExtensionAlias("dist", "osgt");
47}
48
49extViewer::extViewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop) : Viewer(viewer, copyop)
50{
51
52}
53
54extViewer::~extViewer()
55{
56
57}
58
59static osg::Geometry* createMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, unsigned int columns, unsigned int rows, osg::Image* intensityMap, bool applyIntensityMapAsColours, const osg::Matrix& projectorMatrix)
60{
61        // Create Quad to render on
62        osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
63
64        geom->setUseDisplayList( false );
65
66        osg::Vec3 xAxis(widthVector);
67    float width = widthVector.length();
68    xAxis /= width;
69
70    osg::Vec3 yAxis(heightVector);
71    float height = heightVector.length();
72    yAxis /= height;
73
74        osg::Vec3 dx = xAxis*(width/((float)(columns-1)));
75    osg::Vec3 dy = yAxis*(height/((float)(rows-1)));
76
77
78        // Create vertices and coordinates
79        osg::Vec3Array* vertices = new osg::Vec3Array;
80    osg::Vec2Array* texcoords0 = new osg::Vec2Array;
81    osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0;
82    osg::Vec4Array* colors = new osg::Vec4Array;
83
84        geom->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
85
86        for ( unsigned int row=0; row<rows; row++ )
87        {
88                for ( unsigned int col=0; col<columns; col++ )
89                {
90                        // Create coordinates of the mesh node (geometry).
91                        vertices->push_back( origin+dy*row+dx*col );
92
93                        // Create tex coordinates
94                        osg::Vec2 texcoord = osg::Vec2((float)col/(float)(columns-1), (float)row/(float)(rows-1));
95
96                        // Set Coordinates for RTT-Texture (scene rendering)
97                        texcoords0->push_back( texcoord );
98
99                        // Set Color of the mesh node
100                        if (intensityMap && applyIntensityMapAsColours)
101                        {
102                                colors->push_back(intensityMap->getColor(texcoord));
103                        }
104                        else
105                        {
106                                colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
107                        }
108
109                        // Set coordinates for second texcoords array (if applyIntensityMapAsColours==true)
110                        if (texcoords1) 
111                                texcoords1->push_back( texcoord );
112                }
113        }
114
115        // Pass the created vertex array to the points geometry object.
116        geom->setUseVertexBufferObjects( true );
117        geom->setVertexArray(vertices);
118
119        geom->setColorArray(colors);
120    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
121
122    geom->setTexCoordArray(0,texcoords0);
123    if (texcoords1)
124                geom->setTexCoordArray(1,texcoords1);
125
126        // Quads grid
127        for ( unsigned int row=0; row<rows-1; row++ )   // each strip consists of two affected vertex rows, so we need only row-1 strips.
128        {
129                osg::ref_ptr<osg::DrawElementsUInt> de = new osg::DrawElementsUInt(osg::PrimitiveSet::QUAD_STRIP, columns*2);   // columns*2 = number of involved vertices for this strip.
130                for ( unsigned int col=0; col<columns; col++ )
131                {
132                        (*de)[col*2 + 0] = row*columns + col;
133                        (*de)[col*2 + 1] = (row+1)*columns + col;
134                }
135                geom->addPrimitiveSet( de.get() );
136        }
137
138        //// Triangle grid
139        //for ( unsigned int row=0; row<rows-1; row++ ) // each strip consists of two affected vertex rows, so we need only row-1 strips.
140        //{
141        //      osg::ref_ptr<osg::DrawElementsUInt> de = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, columns * 2 );   
142        //      for ( unsigned int col=0; col<columns; col++ )
143        //      {
144        //              (*de)[col*2 + 0] = row*columns + col;
145        //              (*de)[col*2 + 1] = (row+1)*columns + col;
146        //      }
147        //      geom->addPrimitiveSet( de.get() );
148        //}
149
150        return geom.release();
151}
152
153
154void extViewer::setUpViewForManualDistortion(unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix)
155{
156        OSG_INFO<<"View::setUpViewForManualDistortion(sn="<<screenNum<<")"<<std::endl;
157
158        // Create DistortionSet
159        _distortionSet = new osgViewer::DistortionSet();
160        _distortionSet->setIntensityMap( intensityMap );
161        _distortionSet->setDistortionMeshRows( 20 );
162        _distortionSet->setDistortionMeshColumns( 20 );
163
164
165
166
167    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
168    if (!wsi)
169    {
170        OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
171        return;
172    }
173
174        osg::GraphicsContext::ScreenIdentifier si;
175    si.readDISPLAY();
176
177    // displayNum has not been set so reset it to 0.
178    if (si.displayNum<0) si.displayNum = 0;
179
180    si.screenNum = screenNum;
181
182    unsigned int width, height;
183    wsi->getScreenResolution(si, width, height);
184
185        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
186    traits->hostName = si.hostName;
187    traits->displayNum = si.displayNum;
188    traits->screenNum = si.screenNum;
189    traits->x = 0;
190    traits->y = 0;
191    traits->width = width;
192    traits->height = height;
193    traits->windowDecoration = false;
194    traits->doubleBuffer = true;
195    traits->sharedContext = 0;
196
197        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
198    if (!gc)
199    {
200        OSG_NOTICE<<"GraphicsWindow has not been created successfully."<<std::endl;
201        return;
202    }
203
204        // Set up projection Matrix as it is done in View::setUpViewOnSingleScreen(
205        double fovy, aspectRatio, zNear, zFar;
206        _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
207
208        double newAspectRatio = double(traits->width) / double(traits->height);
209        double aspectRatioChange = newAspectRatio / aspectRatio;
210        if (aspectRatioChange != 1.0)
211        {
212                _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
213        }
214
215
216    int tex_width = width;
217    int tex_height = height;
218
219    int camera_width = tex_width;
220    int camera_height = tex_height;
221
222    osg::TextureRectangle* sceneTexture = new osg::TextureRectangle;
223
224    sceneTexture->setTextureSize(tex_width, tex_height);
225    sceneTexture->setInternalFormat(GL_RGB);
226    sceneTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
227    sceneTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
228    sceneTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
229    sceneTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
230
231
232#if 0
233    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
234    GLenum buffer = GL_FRONT;
235#else
236    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
237    GLenum buffer = GL_FRONT;
238#endif
239
240        // Scene camera
241    {
242        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
243        camera->setName("Scene cam");
244        camera->setGraphicsContext(gc.get());
245        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
246        camera->setDrawBuffer(buffer);
247        camera->setReadBuffer(buffer);
248        camera->setAllowEventFocus(false);
249        // tell the camera to use OpenGL frame buffer object where supported.
250        camera->setRenderTargetImplementation(renderTargetImplementation);
251        // attach the texture and use it as the color buffer.
252        camera->attach(osg::Camera::COLOR_BUFFER, sceneTexture);
253
254        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
255    }
256
257    // distortion correction set up.
258    {
259                osg::Geode* geode = new osg::Geode();
260
261                // new we need to add the scene texture to the mesh, we do so by creating a
262        // StateSet to contain the Texture StateAttribute.
263            osg::StateSet* stateset = geode->getOrCreateStateSet();
264        stateset->setTextureAttributeAndModes(_distortionSet->getTexUnitScene(), sceneTexture,osg::StateAttribute::ON);
265        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
266
267                osg::TexMat* texmat = new osg::TexMat;
268            texmat->setScaleByTextureRectangleSize(true);
269        stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
270
271                setUpIntensityMapBlending(_distortionSet, stateset, screenNum);
272
273                osg::Geometry* distortionMesh = createMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), 20, 20, _distortionSet->getIntensityMap(), false, projectorMatrix);
274                geode->addDrawable(distortionMesh);
275
276        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
277        camera->setGraphicsContext(gc.get());
278        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
279        camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
280        camera->setViewport(new osg::Viewport(0, 0, width, height));
281        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
282        camera->setDrawBuffer(buffer);
283        camera->setReadBuffer(buffer);
284        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
285        camera->setAllowEventFocus(false);
286        camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
287        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
288
289        camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
290        camera->setViewMatrix(osg::Matrix::identity());
291
292                // selector
293                geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
294                geode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1.0f, 1.0f) );
295                osg::ref_ptr<distortionHandler> selectorHandler = new distortionHandler( camera, distortionMesh );
296                osg::ref_ptr<osg::Group> root = new osg::Group;
297                root->addChild(geode);
298                osg::Geode* selectorHighlighter = selectorHandler->createVertexHighlighter();
299                selectorHighlighter->setCullingActive(false);   // disable the culling for the selector, otherwise the selector is culled away on the edge.
300                root->addChild(selectorHighlighter);
301                addEventHandler( selectorHandler.get() );
302                camera->addChild(root);
303                // Avoid that the highlighter is culled away
304                osg::CullSettings::CullingMode mode = camera->getCullingMode();
305                camera->setCullingMode( mode & (~osg::CullSettings::SMALL_FEATURE_CULLING) );
306
307                // Add the distortionHandler
308                osgViewer::DistortionManipulator* distManip = new osgViewer::DistortionManipulator();
309                distManip->setDistortionSet(_distortionSet);
310                addEventHandler(distManip);
311
312
313        camera->setName("Dist Cam");
314
315        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
316    }
317}
318
319void extViewer::setUpIntensityMapBlending(osgViewer::DistortionSet* distSet, osg::StateSet* stateset, unsigned int screenNum)
320{
321        osg::Image* intensityMap = _distortionSet->getIntensityMap();
322        if(intensityMap == NULL)        return;
323
324        if(stateset == NULL)
325        {
326                OSG_NOTICE<<"Error, no intensityMap or stateset for intensityMapBlending specified."<<std::endl;
327                return;
328        }
329
330        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
331    if (!wsi)
332    {
333        OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
334        return;
335    }
336
337        osg::GraphicsContext::ScreenIdentifier si;
338    si.readDISPLAY();
339
340    // displayNum has not been set so reset it to 0.
341    if (si.displayNum<0) si.displayNum = 0;
342
343    si.screenNum = screenNum;
344
345    unsigned int width, height;
346    wsi->getScreenResolution(si, width, height);
347
348        // Resize intensityMap if the dimensions are wrong
349        if(intensityMap->s()!=width || intensityMap->t()!=height)
350                intensityMap->scaleImage(width, height, intensityMap->r());
351
352        osg::TextureRectangle* intensityMapTexture = new osg::TextureRectangle(intensityMap);
353        intensityMapTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
354        intensityMapTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
355        intensityMapTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
356        intensityMapTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
357
358    stateset->setTextureAttributeAndModes(_distortionSet->getTexUnitIntensityMap(), intensityMapTexture, osg::StateAttribute::ON);
359
360        // create shaders for blending
361        osg::Program* distortProgram = new osg::Program;
362        distortProgram->setName( "intensityMapBlending" );
363        osg::Shader* fShader = osg::Shader::readShaderFile( osg::Shader::FRAGMENT, "shader.frag" ); 
364        fShader->setName("intensityMapFragShader");
365
366        if ( fShader )
367        {
368                distortProgram->addShader( fShader );
369                //stateset->addUniform( new osg::Uniform("sceneTexture", _distortionSet->getTexUnitScene()) );
370                //stateset->addUniform( new osg::Uniform("intensityMapTexture", _distortionSet->getTexUnitIntensityMap()) );
371                stateset->addUniform( new osg::Uniform("sceneTexture", 0 ) );
372                stateset->addUniform( new osg::Uniform("intensityMapTexture", 1 ) );
373                stateset->setAttributeAndModes(distortProgram, osg::StateAttribute::ON);
374        }
375}
376
377void extViewer::setUpIntensityMapBlending(std::string intensityMap)
378{
379        // Try to load intensityMap
380        osg::Image* intMap = osgDB::readImageFile(intensityMap);
381        if (!intMap)
382        {
383                osg::notify(osg::WARN) << "Quitting, couldn't find intensity map: " << intensityMap << std::endl;
384                return;
385        } 
386
387        // Create DistortionSet
388        _distortionSet = new osgViewer::DistortionSet();
389        _distortionSet->setIntensityMap( intMap );
390        _distortionSet->setDistortionMeshRows( 1 );
391        _distortionSet->setDistortionMeshColumns( 1 );
392        _distortionSet->setTexUnitScene( 0 );
393        _distortionSet->setTexUnitIntensityMap( 1 );
394
395        // Todo: call setupDistortion/Blendung to perform the blending
396}
Note: See TracBrowser for help on using the repository browser.