source: experimental/distortionNG/extViewer.cpp @ 341

Last change on this file since 341 was 341, checked in by Torben Dannhauer, 12 years ago

intensityBlending is now supported. Code refactored to have a single setup method

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