source: experimental/distortionNG/extViewer.cpp @ 352

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