root/OpenSceneGraph/trunk/examples/osgparametric/osgparametric.cpp @ 5863

Revision 5863, 19.8 kB (checked in by robert, 8 years ago)

Various work on osgViewer library, including warp point and graphics window resize support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Vec3>
2#include <osg/Vec4>
3#include <osg/Quat>
4#include <osg/Matrix>
5#include <osg/ShapeDrawable>
6#include <osg/Geometry>
7#include <osg/Geode>
8#include <osg/Texture2D>
9
10#include <osgDB/FileUtils>
11#include <osgDB/ReadFile>
12
13#include <osgUtil/Optimizer>
14#include <osgUtil/TriStripVisitor>
15
16#include <osgProducer/Viewer>
17
18// for the grid data..
19#include "../osghangglide/terrain_coords.h"
20
21///////////////////////////////////////////////////////////////////
22// vertex shader using just Vec4 coefficients
23char vertexShaderSource_simple[] =
24    "uniform vec4 coeff; \n"
25    "\n"
26    "void main(void) \n"
27    "{ \n"
28    "\n"
29    "    gl_TexCoord[0] = gl_Vertex; \n"
30    "    vec4 vert = gl_Vertex; \n"
31    "    vert.z = gl_Vertex.x*coeff[0] + gl_Vertex.x*gl_Vertex.x* coeff[1] + \n"
32    "             gl_Vertex.y*coeff[2] + gl_Vertex.y*gl_Vertex.y* coeff[3]; \n"
33    "    gl_Position = gl_ModelViewProjectionMatrix * vert;\n"
34    "}\n";
35 
36 
37//////////////////////////////////////////////////////////////////
38// vertex shader using full Matrix4 coefficients
39char vertexShaderSource_matrix[] =
40    "uniform vec4  origin; \n"
41    "uniform mat4  coeffMatrix; \n"
42    "\n"
43    "void main(void) \n"
44    "{ \n"
45    "\n"
46    "    gl_TexCoord[0] = gl_Vertex; \n"
47    "    vec4 v = vec4(gl_Vertex.x, gl_Vertex.x*gl_Vertex.x, gl_Vertex.y, gl_Vertex.y*gl_Vertex.y ); \n"
48    "    gl_Position = gl_ModelViewProjectionMatrix * (origin + coeffMatrix * v);\n"
49    "}\n";
50
51//////////////////////////////////////////////////////////////////
52// vertex shader using texture read
53char vertexShaderSource_texture[] =
54    "uniform sampler2D vertexTexture; \n"
55    "\n"
56    "void main(void) \n"
57    "{ \n"
58    "\n"
59    "    gl_TexCoord[0] = gl_Vertex; \n"
60    "    vec4 vert = gl_Vertex; \n"
61    "    vert.z = texture2D( vertexTexture, gl_TexCoord[0].xy).x*0.1; \n"
62    "    gl_Position = gl_ModelViewProjectionMatrix * vert;\n"
63    "}\n";
64
65//////////////////////////////////////////////////////////////////
66// vertex shader using texture read
67char vertexShaderSource_texture2[] =
68    "uniform sampler2D vertexTexture; \n"
69    "uniform sampler2D vertexTexture2; \n"
70    "uniform float osg_FrameTime;\n"
71    "\n"
72    "void main(void) \n"
73    "{ \n"
74    "\n"
75    "    gl_TexCoord[0] = gl_Vertex; \n"
76    "    vec4 vert = gl_Vertex; \n"
77    "    float r = 1.0 + 0.5 * sin(osg_FrameTime);\n"
78    "    vert.z = (texture2D( vertexTexture, gl_TexCoord[0].xy).x * (1-r) + texture2D( vertexTexture2, gl_TexCoord[0].xy).x * r)*0.1; \n"
79    "    gl_Position = gl_ModelViewProjectionMatrix * vert;\n"
80    "}\n";
81
82//////////////////////////////////////////////////////////////////
83// fragment shader
84//
85char fragmentShaderSource[] =
86    "uniform sampler2D baseTexture; \n"
87    "\n"
88    "void main(void) \n"
89    "{ \n"
90    "    gl_FragColor = texture2D( baseTexture, gl_TexCoord[0].xy); \n"
91    "}\n";
92
93#if 0
94char fragmentShaderNormalSource[] =
95    "uniform sampler2D baseTexture; \n"
96    "uniform sampler2D vertexTexture; \n"
97    "\n"
98    "void main(void) \n"
99    "{ \n"
100    "    const float dx = 0.0010;  \n"
101    "    const float dy = 0.0010;  \n"
102    "    float dz_dx = texture2D( vertexTexture, gl_TexCoord[0].xy + vec2(dx,0.0)).x - texture2D( vertexTexture, gl_TexCoord[0].xy + vec2(-dx,0.0)).x; \n"
103    "    float dz_dy = texture2D( vertexTexture, gl_TexCoord[0].xy + vec2(0.0,dy)).x - texture2D( vertexTexture, gl_TexCoord[0].xy + vec2(0.0,-dy)).x; \n"
104    "    vec3 normal = normalize(vec3(-dz_dx, -dz_dy, dx*50));\n"
105    " \n"
106    "    gl_FragColor = vec4(normal.z,normal.z,normal.z,1.0); \n"
107    "}\n";
108#else
109char fragmentShaderNormalSource[] =
110    "uniform sampler2D baseTexture; \n"
111    "uniform sampler2D vertexTexture; \n"
112    "\n"
113    "void main(void) \n"
114    "{ \n"
115    "    vec3 normal = normalize(texture2D( baseTexture, gl_TexCoord[0].xy).xyz);\n"
116    " \n"
117    "    gl_FragColor = vec4(normal.z,normal.z,normal.z,1.0); \n"
118    "}\n";
119#endif
120
121class UniformVarying : public osg::Uniform::Callback
122{
123    virtual void operator () (osg::Uniform* uniform, osg::NodeVisitor* nv)
124    {
125        const osg::FrameStamp* fs = nv->getFrameStamp();
126        float value = sinf(fs->getReferenceTime());
127        uniform->set(osg::Vec4(value,-value,-value,value));
128    }
129};
130
131osg::Node* createModel(const std::string& shader, const std::string& textureFileName, const std::string& terrainFileName, const std::string& terrainFileName2, unsigned int cacheSize, unsigned int maxSize, bool joinStrips, const std::string& mesh)
132{
133    osg::Geode* geode = new osg::Geode;
134   
135    osg::Geometry* geom = new osg::Geometry;
136    geode->addDrawable(geom);
137   
138    // dimensions for ~one million triangles :-)
139    unsigned int num_x = 708;
140    unsigned int num_y = 708;
141
142    // set up state
143    {
144   
145        osg::StateSet* stateset = geom->getOrCreateStateSet();
146
147        osg::Program* program = new osg::Program;
148        stateset->setAttribute(program);
149
150        if (shader=="simple")
151        {
152            osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource_simple);
153            program->addShader(vertex_shader);
154
155            osg::Uniform* coeff = new osg::Uniform("coeff",osg::Vec4(1.0,-1.0f,-1.0f,1.0f));
156            coeff->setUpdateCallback(new UniformVarying);
157            stateset->addUniform(coeff);
158        }
159        else if (shader=="matrix")
160        {
161            osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource_matrix);
162            program->addShader(vertex_shader);
163
164            osg::Uniform* origin = new osg::Uniform("origin",osg::Vec4(0.0f,0.0f,0.0f,1.0f));
165            stateset->addUniform(origin);
166
167            osg::Uniform* coeffMatrix = new osg::Uniform("coeffMatrix",
168                osg::Matrix(1.0f,0.0f,1.0f,0.0f,
169                            0.0f,0.0f,-1.0f,0.0f,
170                            0.0f,1.0f,-1.0f,0.0f,
171                            0.0f,0.0f,1.0f,0.0f));
172
173            stateset->addUniform(coeffMatrix);
174        }
175        else if (shader=="texture")
176        {
177
178            osg::Image* image = 0;
179
180            if (terrainFileName.empty())
181            {
182                image = new osg::Image;
183                unsigned int tx = 38;
184                unsigned int ty = 39;
185                image->allocateImage(tx,ty,1,GL_LUMINANCE,GL_FLOAT,1);
186                for(unsigned int r=0;r<ty;++r)
187                {
188                    for(unsigned int c=0;c<tx;++c)
189                    {
190                        *((float*)image->data(c,r)) = vertex[r+c*39][2]*0.1;
191                    }
192                }
193
194                num_x = tx;
195                num_y = tx;
196            }
197            else
198            {
199                image = osgDB::readImageFile(terrainFileName);
200
201                num_x = image->s();
202                num_y = image->t();
203            }
204
205            osg::Texture2D* vertexTexture = new osg::Texture2D(image);
206
207
208            vertexTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::NEAREST);
209            vertexTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::NEAREST);
210           
211            vertexTexture->setInternalFormat(GL_LUMINANCE_FLOAT32_ATI);
212           
213            vertexTexture->setResizeNonPowerOfTwoHint(false);
214            stateset->setTextureAttributeAndModes(1,vertexTexture);
215
216            osg::Uniform* vertexTextureSampler = new osg::Uniform("vertexTexture",1);
217            stateset->addUniform(vertexTextureSampler);
218
219            if (!terrainFileName2.empty())
220            {
221                osg::Image* image2 = osgDB::readImageFile(terrainFileName2);
222                osg::Texture2D* vertexTexture2 = new osg::Texture2D(image2);
223
224
225                vertexTexture2->setFilter(osg::Texture::MIN_FILTER,osg::Texture::NEAREST);
226                vertexTexture2->setFilter(osg::Texture::MAG_FILTER,osg::Texture::NEAREST);
227
228                vertexTexture2->setInternalFormat(GL_LUMINANCE_FLOAT32_ATI);
229
230                vertexTexture2->setResizeNonPowerOfTwoHint(false);
231                stateset->setTextureAttributeAndModes(2,vertexTexture2);
232
233                osg::Uniform* vertexTextureSampler2 = new osg::Uniform("vertexTexture2",2);
234                stateset->addUniform(vertexTextureSampler2);
235
236            }
237
238        }
239
240        if (terrainFileName2.empty())
241        {
242            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderNormalSource);
243            program->addShader(fragment_shader);
244
245            osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource_texture);
246            program->addShader(vertex_shader);
247        }
248        else
249        {
250
251            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
252            program->addShader(fragment_shader);
253
254            osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource_texture2);
255            program->addShader(vertex_shader);
256        }
257       
258        osg::Texture2D* texture = new osg::Texture2D(osgDB::readImageFile(textureFileName));
259        stateset->setTextureAttributeAndModes(0,texture);
260
261        osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
262        stateset->addUniform(baseTextureSampler);
263
264    }
265
266
267    // set up geometry data.
268
269    osg::Vec3Array* vertices = new osg::Vec3Array( num_x * num_y );
270   
271    float dx = 1.0f/(float)(num_x-1);
272    float dy = 1.0f/(float)(num_y-1);
273    osg::Vec3 row(0.0f,0.0f,0.0);
274   
275    unsigned int vert_no = 0;
276    unsigned int iy;
277    for(iy=0; iy<num_y; ++iy)
278    {
279        osg::Vec3 column = row;
280        for(unsigned int ix=0;ix<num_x;++ix)
281        {
282            (*vertices)[vert_no++] = column;
283            column.x() += dx;
284        }       
285        row.y() += dy;
286    }
287
288    geom->setVertexArray(vertices);
289
290    unsigned int totalIndices = 0;
291    if (mesh=="triangles" || mesh=="tristrip")
292    {
293        if (cacheSize)
294        {
295            unsigned int index=0;
296            osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLES);
297            geom->addPrimitiveSet(elements);   
298            elements->dirty();
299           
300            for(unsigned int is=0; is<num_x; is += cacheSize-1)
301            {
302           
303                for(iy=0; iy<num_y-1; ++iy)
304                {
305                    unsigned int num_in_stripe = osg::minimum(cacheSize, num_x-is);
306                   
307                    bool rightToLeft = true;
308
309                    if (elements->size() > maxSize)
310                    {
311                        osg::notify(osg::NOTICE)<<"elements->size() = "<<elements->size()<<std::endl;
312                        totalIndices += elements->size();
313
314                        index=0;
315                        elements = new osg::DrawElementsUInt(GL_TRIANGLES);
316                        geom->addPrimitiveSet(elements);   
317                        elements->dirty();
318
319                    }
320
321                    if (rightToLeft)
322                    {
323
324                        index = iy * num_x + is;
325
326                        for(unsigned int ix = 0; ix<num_in_stripe-1; ++ix)
327                        {
328                            (*elements).push_back(index + num_x);
329                            (*elements).push_back(index);
330                            (*elements).push_back(index+1);
331
332                            (*elements).push_back(index + num_x);
333                            (*elements).push_back(index+1);
334                            (*elements).push_back(index + num_x + 1);
335
336                            ++index;
337                        }
338                    }
339                    else
340                    {
341                        index = iy * num_x + is + (num_x-2);
342
343                        for(unsigned int ix = 0; ix<num_in_stripe-1; ++ix)
344                        {
345                            (*elements).push_back(index + num_x);
346                            (*elements).push_back(index);
347                            (*elements).push_back(index+1);
348
349                            (*elements).push_back(index + num_x);
350                            (*elements).push_back(index+1);
351                            (*elements).push_back(index + num_x + 1);
352
353                            --index;
354                        }
355                    }
356                   
357                    rightToLeft = !rightToLeft;                   
358                   
359                }
360               
361            }
362            totalIndices += elements->size();
363            osg::notify(osg::NOTICE)<<"elements->size() = "<<elements->size()<<std::endl;
364        }
365        else
366        {
367            osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLES, (num_x-1)*(num_y-1)*6);
368            elements->dirty();
369            unsigned int element_no = 0;
370            for(iy=0; iy<num_y-1; ++iy)
371            {
372                unsigned int index = iy * num_x;
373                for(unsigned int ix = 0; ix<num_x-1; ++ix)
374                {
375                    (*elements)[element_no++] = index + num_x;
376                    (*elements)[element_no++] = index;
377                    (*elements)[element_no++] = index+1;
378
379                    (*elements)[element_no++] = index + num_x;
380                    (*elements)[element_no++] = index+1;
381                    (*elements)[element_no++] = index + num_x + 1;
382                   
383                    ++index;
384                }
385            }
386            geom->addPrimitiveSet(elements);   
387            osg::notify(osg::NOTICE)<<"elements->size() = "<<elements->size()<<std::endl;
388        }
389    }
390    else
391    {
392   
393        if (cacheSize)
394        {
395            bool needToJoin = false;
396            unsigned int index=0;
397            osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP);
398            geom->addPrimitiveSet(elements);   
399            elements->dirty();
400
401            for(unsigned int is=0; is<num_x; is += cacheSize-1)
402            {
403           
404                for(iy=0; iy<num_y-1; ++iy)
405                {
406                    unsigned int num_in_stripe = osg::minimum(cacheSize, num_x-is);
407                   
408                    bool rightToLeft = true;
409
410                    if (elements->size() > maxSize)
411                    {
412                        osg::notify(osg::NOTICE)<<"elements->size() = "<<elements->size()<<std::endl;
413
414                        totalIndices += elements->size();
415
416                        needToJoin = false;
417                        index=0;
418                        elements = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP);
419                        geom->addPrimitiveSet(elements);   
420                        elements->dirty();
421
422                    }
423
424                    if (needToJoin) (*elements).push_back(elements->back());
425                   
426                    if (rightToLeft)
427                    {
428
429                        index = iy * num_x + is;
430
431                        if (needToJoin) (*elements).push_back(index + num_x);
432
433                        for(unsigned int ix = 0; ix<num_in_stripe; ++ix)
434                        {
435                            (*elements).push_back(index + num_x);
436                            (*elements).push_back(index++);
437                        }
438                    }
439                    else
440                    {
441                        index = iy * num_x + is + (num_x-1);
442
443                        if (needToJoin) (*elements).push_back(index);
444
445                        for(unsigned int ix = 0; ix<num_in_stripe; ++ix)
446                        {
447                            (*elements).push_back(index);
448                            (*elements).push_back(index-- + num_x);
449                        }
450                    }
451                   
452                    rightToLeft = !rightToLeft;                   
453                   
454                    needToJoin = true;
455                }
456               
457            }
458            totalIndices += elements->size();
459        }
460        else
461        {
462            osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP);
463            elements->dirty();
464            geom->addPrimitiveSet(elements);   
465            bool needToJoin = false;
466            unsigned int index=0;
467            for(iy=0; iy<num_y-1; ++iy)
468            {
469
470                if (needToJoin) (*elements).push_back(index-1);
471
472                index = iy * num_x;
473
474                if (needToJoin) (*elements).push_back(index + num_x);
475
476                for(unsigned int ix = 0; ix<num_x; ++ix)
477                {
478                    (*elements).push_back(index + num_x);
479                    (*elements).push_back(index++);
480                }
481                needToJoin = true;
482
483            }
484        }
485    }
486
487    osg::notify(osg::NOTICE)<<"totalIndices = "<<totalIndices<<std::endl;
488
489    if (mesh=="tristrip")
490    {   osgUtil::TriStripVisitor stripper;
491        stripper.stripify(*geom);
492    }
493
494#if 0
495    geom->setUseVertexBufferObjects(true);
496#else
497    geom->setUseVertexBufferObjects(false);
498#endif
499
500    return geode;
501}
502
503int main(int argc, char *argv[])
504{
505    // use an ArgumentParser object to manage the program arguments.
506    osg::ArgumentParser arguments(&argc,argv);
507
508    // set up the usage document, in case we need to print out how to use this program.
509    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrate support for ARB_vertex_program.");
510    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
511    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
512   
513    // construct the viewer.
514    osgProducer::Viewer viewer(arguments);
515
516    // set up the value with sensible default event handlers.
517    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
518   
519    std::string shader("simple");
520    while(arguments.read("-s",shader)) {}
521   
522    std::string textureFileName("Images/lz.rgb");
523    while(arguments.read("-t",textureFileName)) {}
524
525    std::string terrainFileName("");
526    while(arguments.read("-d",terrainFileName)) {}
527
528    std::string terrainFileName2("");
529    while(arguments.read("-d2",terrainFileName2)) {}
530
531    unsigned int cacheSize = 0;
532    while(arguments.read("--cache",cacheSize)) {}
533
534    unsigned int maxSize = 2048;
535    while(arguments.read("--max",maxSize)) {}
536
537    std::string mesh("strip");
538    while(arguments.read("--mesh",mesh)) {}
539
540    bool joinStrips = false;
541    while(arguments.read("--join")) { joinStrips = true; }
542
543    // get details on keyboard and mouse bindings used by the viewer.
544    viewer.getUsage(*arguments.getApplicationUsage());
545
546    // if user request help write it out to cout.
547    if (arguments.read("-h") || arguments.read("--help"))
548    {
549        arguments.getApplicationUsage()->write(std::cout);
550        return 1;
551    }
552
553    // any option left unread are converted into errors to write out later.
554    arguments.reportRemainingOptionsAsUnrecognized();
555
556    // report any errors if they have occured when parsing the program aguments.
557    if (arguments.errors())
558    {
559        arguments.writeErrorMessages(std::cout);
560        return 1;
561    }
562
563    // load the nodes from the commandline arguments.
564    osg::Node* model = createModel(shader,textureFileName,terrainFileName,terrainFileName2, cacheSize, maxSize, joinStrips,mesh);
565    if (!model)
566    {
567        return 1;
568    }
569
570    // add a viewport to the viewer and attach the scene graph.
571    viewer.setSceneData(model);
572   
573    // create the windows and run the threads.
574    viewer.realize();
575
576    while( !viewer.done() )
577    {
578        // wait for all cull and draw threads to complete.
579        viewer.sync();
580
581        // update the scene by traversing it with the the update visitor which will
582        // call all node update callbacks and animations.
583        viewer.update();
584         
585        // fire off the cull and draw traversals of the scene.
586        viewer.frame();
587       
588    }
589   
590    // wait for all cull and draw threads to complete.
591    viewer.sync();
592
593    // run a clean up frame to delete all OpenGL objects.
594    viewer.cleanup_frame();
595
596    // wait for all the clean up frame to complete.
597    viewer.sync();
598
599    return 0;
600}
Note: See TracBrowser for help on using the browser.