source: experimental/distortionNG/extViewer.cpp @ 345

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