source: experimental/distortionNG/extViewer.cpp @ 353

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

DistortionManipulator? is working (alpha stadium)

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