source: experimental/distortionNG/extViewer.cpp @ 338

Last change on this file since 338 was 338, checked in by Torben Dannhauer, 12 years ago
File size: 13.1 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::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
47            //texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
48            //texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
49            //texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
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
63static 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
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(GL_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        return geom.release();
167}
168
169void extViewer::setUpViewForManualDistortion(unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix)
170{
171        OSG_INFO<<"View::setUpViewForManualDistortion(sn="<<screenNum<<", im="<<intensityMap<<")"<<std::endl;
172
173    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
174    if (!wsi)
175    {
176        OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
177        return;
178    }
179
180        osg::GraphicsContext::ScreenIdentifier si;
181    si.readDISPLAY();
182
183    // displayNum has not been set so reset it to 0.
184    if (si.displayNum<0) si.displayNum = 0;
185
186    si.screenNum = screenNum;
187
188    unsigned int width, height;
189    wsi->getScreenResolution(si, width, height);
190
191        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
192    traits->hostName = si.hostName;
193    traits->displayNum = si.displayNum;
194    traits->screenNum = si.screenNum;
195    traits->x = 0;
196    traits->y = 0;
197    traits->width = width;
198    traits->height = height;
199    traits->windowDecoration = false;
200    traits->doubleBuffer = true;
201    traits->sharedContext = 0;
202
203        bool applyIntensityMapAsColours = false;
204
205        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
206    if (!gc)
207    {
208        OSG_NOTICE<<"GraphicsWindow has not been created successfully."<<std::endl;
209        return;
210    }
211
212        // Set up projection Matrix as it is done in View::setUpViewOnSingleScreen(
213        double fovy, aspectRatio, zNear, zFar;
214        _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
215
216        double newAspectRatio = double(traits->width) / double(traits->height);
217        double aspectRatioChange = newAspectRatio / aspectRatio;
218        if (aspectRatioChange != 1.0)
219        {
220                _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
221        }
222
223
224    int tex_width = width;
225    int tex_height = height;
226
227    int camera_width = tex_width;
228    int camera_height = tex_height;
229
230    osg::TextureRectangle* sceneTexture = new osg::TextureRectangle;
231
232    sceneTexture->setTextureSize(tex_width, tex_height);
233    sceneTexture->setInternalFormat(GL_RGB);
234    sceneTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
235    sceneTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
236    sceneTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
237    sceneTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
238
239
240#if 0
241    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
242    GLenum buffer = GL_FRONT;
243#else
244    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
245    GLenum buffer = GL_FRONT;
246#endif
247
248        // Scene camera
249    {
250        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
251        camera->setName("Scene cam");
252        camera->setGraphicsContext(gc.get());
253        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
254        camera->setDrawBuffer(buffer);
255        camera->setReadBuffer(buffer);
256        camera->setAllowEventFocus(false);
257        // tell the camera to use OpenGL frame buffer object where supported.
258        camera->setRenderTargetImplementation(renderTargetImplementation);
259        // attach the texture and use it as the color buffer.
260        camera->attach(osg::Camera::COLOR_BUFFER, sceneTexture);
261
262        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
263    }
264
265    // distortion correction set up.
266    {
267                osg::Geode* geode = new osg::Geode();
268
269                // new we need to add the scene texture to the mesh, we do so by creating a
270        // StateSet to contain the Texture StateAttribute.
271            osg::StateSet* stateset = geode->getOrCreateStateSet();
272        stateset->setTextureAttributeAndModes(0, sceneTexture,osg::StateAttribute::ON);
273        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
274
275                osg::TexMat* texmat = new osg::TexMat;
276            texmat->setScaleByTextureRectangleSize(true);
277        stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
278
279                // If the intensityMap is used but not applyIntensityMapAsColours: Apply intensityMap as intensityMapTexture on unit 1
280                if (!applyIntensityMapAsColours && intensityMap)
281        {
282                        // Resize intensityMap if the dimensions are wrong
283                        if(intensityMap->s()!=tex_width || intensityMap->t()!=tex_height)
284                                intensityMap->scaleImage(tex_width, tex_height, intensityMap->r());
285
286                        osg::TextureRectangle* intensityMapTexture = new osg::TextureRectangle(intensityMap);
287                        intensityMapTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
288                        intensityMapTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
289                        intensityMapTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
290                        intensityMapTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
291
292            stateset->setTextureAttributeAndModes(1, intensityMapTexture, osg::StateAttribute::ON);
293
294                        // create shaders for distortion
295                        osg::Program* distortProgram = new osg::Program;
296                        distortProgram->setName( "distortion" );
297                        osg::Shader* vShader = osg::Shader::readShaderFile( osg::Shader::VERTEX, "shader.vert" ); 
298                        vShader->setName("intensityMapVertShader");
299                        osg::Shader* fShader = osg::Shader::readShaderFile( osg::Shader::FRAGMENT, "shader.frag" ); 
300                        fShader->setName("intensityMapFragShader");
301
302                        if ( vShader && fShader )
303                        {
304                                //distortProgram->addShader( vShader );
305                                distortProgram->addShader( fShader );
306                                stateset->addUniform( new osg::Uniform("sceneTexture", 0) );
307                                stateset->addUniform( new osg::Uniform("intensityMapTexture", 1) );
308                                stateset->setAttributeAndModes(distortProgram, osg::StateAttribute::ON);
309                        }
310        }
311
312                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);
313                geode->addDrawable(distortionMesh);
314
315        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
316        camera->setGraphicsContext(gc.get());
317        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
318        camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
319        camera->setViewport(new osg::Viewport(0, 0, width, height));
320        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
321        camera->setDrawBuffer(buffer);
322        camera->setReadBuffer(buffer);
323        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
324        camera->setAllowEventFocus(false);
325        camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
326        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
327
328        camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
329        camera->setViewMatrix(osg::Matrix::identity());
330
331                // selector
332                geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
333                geode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1.0f, 1.0f) );
334                osg::ref_ptr<distortionHandler> selector = new distortionHandler( camera, distortionMesh );
335                osg::ref_ptr<osg::Group> root = new osg::Group;
336                root->addChild(geode);
337                root->addChild(selector->createVertexHighlighter());
338                addEventHandler( selector.get() );
339                camera->addChild(root);
340                // Avoid that the highlighter is culled away
341                osg::CullSettings::CullingMode mode = camera->getCullingMode();
342                camera->setCullingMode( mode & (~osg::CullSettings::SMALL_FEATURE_CULLING) );
343
344
345        camera->setName("Dist Cam");
346
347        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
348    }
349}
Note: See TracBrowser for help on using the repository browser.