source: experimental/distortionNG/extViewer.cpp @ 394

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

vertex- and texcoord warping works now :)

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