source: experimental/distortionNG/extViewer.cpp @ 339

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

Mesh can now be triangle_strip or quad_strip

-> important to fix vertex selector working :)

File size: 13.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        {
290                        // Resize intensityMap if the dimensions are wrong
291                        if(intensityMap->s()!=tex_width || intensityMap->t()!=tex_height)
292                                intensityMap->scaleImage(tex_width, tex_height, intensityMap->r());
293
294                        osg::TextureRectangle* intensityMapTexture = new osg::TextureRectangle(intensityMap);
295                        intensityMapTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
296                        intensityMapTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
297                        intensityMapTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
298                        intensityMapTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
299
300            stateset->setTextureAttributeAndModes(1, intensityMapTexture, osg::StateAttribute::ON);
301
302                        // create shaders for distortion
303                        osg::Program* distortProgram = new osg::Program;
304                        distortProgram->setName( "distortion" );
305                        osg::Shader* vShader = osg::Shader::readShaderFile( osg::Shader::VERTEX, "shader.vert" ); 
306                        vShader->setName("intensityMapVertShader");
307                        osg::Shader* fShader = osg::Shader::readShaderFile( osg::Shader::FRAGMENT, "shader.frag" ); 
308                        fShader->setName("intensityMapFragShader");
309
310                        if ( vShader && fShader )
311                        {
312                                //distortProgram->addShader( vShader );
313                                distortProgram->addShader( fShader );
314                                stateset->addUniform( new osg::Uniform("sceneTexture", 0) );
315                                stateset->addUniform( new osg::Uniform("intensityMapTexture", 1) );
316                                stateset->setAttributeAndModes(distortProgram, osg::StateAttribute::ON);
317                        }
318        }
319
320                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);
321                geode->addDrawable(distortionMesh);
322
323        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
324        camera->setGraphicsContext(gc.get());
325        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
326        camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
327        camera->setViewport(new osg::Viewport(0, 0, width, height));
328        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
329        camera->setDrawBuffer(buffer);
330        camera->setReadBuffer(buffer);
331        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
332        camera->setAllowEventFocus(false);
333        camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
334        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
335
336        camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
337        camera->setViewMatrix(osg::Matrix::identity());
338
339                // selector
340                geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
341                geode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1.0f, 1.0f) );
342                osg::ref_ptr<distortionHandler> selector = new distortionHandler( camera, distortionMesh );
343                osg::ref_ptr<osg::Group> root = new osg::Group;
344                root->addChild(geode);
345                root->addChild(selector->createVertexHighlighter());
346                addEventHandler( selector.get() );
347                camera->addChild(root);
348                // Avoid that the highlighter is culled away
349                osg::CullSettings::CullingMode mode = camera->getCullingMode();
350                camera->setCullingMode( mode & (~osg::CullSettings::SMALL_FEATURE_CULLING) );
351
352
353        camera->setName("Dist Cam");
354
355        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
356    }
357}
Note: See TracBrowser for help on using the repository browser.