source: experimental/distortionNG/extViewer.cpp @ 349

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