changed: gcc8 base update
[opensg.git] / Examples / Simple / clusterclientshader.cpp
blob63ad167210f009471f3bbd51daadbfcf12d3c2f1
1 // OpenSG Tutorial Example: Minimalistic OpenSG cluster client program
2 //
3 // To test it, run
4 // ./clusterserver -geometry 300x300+200+100 -m -w test1 &
5 // ./clusterserver -geometry 300x300+500+100 -m -w test2 &
6 // ./clusterclientshader -m -fData/tie.wrl test1 test2
7 //
8 // If you have trouble with multicasting, you can alternatively try
9 // ./clusterserver -geometry 300x300+200+100 -w 127.0.0.1:30000 &
10 // ./clusterserver -geometry 300x300+500+100 -w 127.0.0.1:30001 &
11 // ./clusterclientshader -m -fData/tie.wrl 127.0.0.1:30000 127.0.0.1:30001
12 //
13 // The client will open an empty window that you can use to navigate. The
14 // display is shown in the server windows.
16 // This will run all three on the same machine, but you can also start the
17 // servers anywhere else, as long as you can reach them via multicast.
19 // Note: This will run two VERY active OpenGL programs on one screen. Not all
20 // OpenGL drivers are happy with that, so if it crashes your X, it's not our
21 // fault! ;)
23 // Libs: Cluster
25 #ifdef OSG_BUILD_ACTIVE
26 // GLUT is used for window handling
27 #include <OSGGLUT.h>
29 // General OpenSG configuration, needed everywhere
30 #include <OSGConfig.h>
32 // Methods to create simple geometry: boxes, spheres, tori etc.
33 #include <OSGSimpleGeometry.h>
35 // The GLUT-OpenSG connection class
36 #include <OSGGLUTWindow.h>
38 // A little helper to simplify scene management and interaction
39 #include <OSGSimpleSceneManager.h>
41 // A little helper to simplify scene management and interaction
42 #include <OSGMultiDisplayWindow.h>
44 // Scene file handler for loading geometry files
45 #include <OSGSceneFileHandler.h>
47 #include <OSGImage.h>
48 #include <OSGChunkMaterial.h>
49 #include <OSGMaterialChunk.h>
50 #include <OSGTextureObjChunk.h>
51 #include <OSGTextureEnvChunk.h>
52 #include <OSGSHLChunk.h>
53 #else
54 // GLUT is used for window handling
55 #include <OpenSG/OSGGLUT.h>
57 // General OpenSG configuration, needed everywhere
58 #include <OpenSG/OSGConfig.h>
60 // Methods to create simple geometry: boxes, spheres, tori etc.
61 #include <OpenSG/OSGSimpleGeometry.h>
63 // The GLUT-OpenSG connection class
64 #include <OpenSG/OSGGLUTWindow.h>
66 // A little helper to simplify scene management and interaction
67 #include <OpenSG/OSGSimpleSceneManager.h>
69 // A little helper to simplify scene management and interaction
70 #include <OpenSG/OSGMultiDisplayWindow.h>
72 // Scene file handler for loading geometry files
73 #include <OpenSG/OSGSceneFileHandler.h>
75 #include <OpenSG/OSGImage.h>
76 #include <OpenSG/OSGChunkMaterial.h>
77 #include <OpenSG/OSGMaterialChunk.h>
78 #include <OpenSG/OSGTextureObjChunk.h>
79 #include <OpenSG/OSGTextureEnvChunk.h>
80 #include <OpenSG/OSGSHLChunk.h>
81 #endif
83 // The SimpleSceneManager to manage simple applications
84 SimpleSceneManagerRefPtr mgr;
86 SHLChunkRefPtr _shl;
87 Int32 _animation = 1;
89 // forward declaration so we can have the interesting stuff upfront
90 int setupGLUT( int *argc, char *argv[] );
94 Note the use of NodeTransitPtr as return type for the function.
95 TransitPtr are intended as return types from functions that create
96 objects (factory functions). They can only be assigned to a smart pointer
97 type (RefPtr, MTRefPtr, UnrecPtr), but not to a raw C pointer. Therefore
98 the use of this return type prevents you from accidentally loosing all
99 references to a newly created object (as would happen if you assigned to
100 a raw C pointer).
101 It is strongly recommended to follow the practice of making all factory
102 functions return TransitPtr in order to prevent this hard to find class of
103 bugs.
106 NodeTransitPtr createScene(void)
108 NodeRefPtr _scene;
110 // Create the shader material
111 ChunkMaterialRefPtr cmat = ChunkMaterial::create();
113 // Read the image for the normal texture
114 ImageRefPtr earth_map_img = Image::create();
115 if(!earth_map_img->read("Earth.jpg"))
117 fprintf(stderr, "Couldn't read texture 'Earth.jpg'\n");
118 return NodeTransitPtr();
120 TextureObjChunkRefPtr tex_earth = TextureObjChunk::create();
121 TextureEnvChunkRefPtr tex_earth_env = TextureEnvChunk::create();
123 tex_earth->setImage(earth_map_img);
124 tex_earth->setMinFilter(GL_LINEAR_MIPMAP_LINEAR);
125 tex_earth->setMagFilter(GL_LINEAR);
126 tex_earth->setWrapS(GL_REPEAT);
127 tex_earth->setWrapT(GL_REPEAT);
129 tex_earth_env->setEnvMode(GL_MODULATE);
131 // Read the image for the normal texture
132 ImageRefPtr earth_night_map_img = Image::create();
133 if(!earth_night_map_img->read("EarthNight.jpg"))
135 fprintf(stderr, "Couldn't read texture 'EarthNight.jpg'\n");
136 return NodeTransitPtr();
139 TextureObjChunkRefPtr tex_earth_night = TextureObjChunk::create();
140 TextureEnvChunkRefPtr tex_earth_night_env = TextureEnvChunk::create();
142 tex_earth_night->setImage(earth_night_map_img);
143 tex_earth_night->setMinFilter(GL_LINEAR_MIPMAP_LINEAR);
144 tex_earth_night->setMagFilter(GL_LINEAR);
145 tex_earth_night->setWrapS(GL_REPEAT);
146 tex_earth_night->setWrapT(GL_REPEAT);
148 tex_earth_night_env->setEnvMode(GL_MODULATE);
150 // Read the image for the normal texture
151 ImageRefPtr earth_clouds_map_img = Image::create();
152 if(!earth_clouds_map_img->read("EarthClouds.jpg"))
154 fprintf(stderr, "Couldn't read texture 'EarthClouds.jpg'\n");
155 return NodeTransitPtr();
158 TextureObjChunkRefPtr tex_earth_clouds = TextureObjChunk::create();
159 TextureEnvChunkRefPtr tex_earth_clouds_env = TextureEnvChunk::create();
161 tex_earth_clouds->setImage(earth_clouds_map_img);
162 tex_earth_clouds->setMinFilter(GL_LINEAR_MIPMAP_LINEAR);
163 tex_earth_clouds->setMagFilter(GL_LINEAR);
164 tex_earth_clouds->setWrapS(GL_REPEAT);
165 tex_earth_clouds->setWrapT(GL_REPEAT);
167 tex_earth_clouds_env->setEnvMode(GL_MODULATE);
170 _shl = SHLChunk::create();
172 if(!_shl->readVertexProgram("Earth.vp"))
173 fprintf(stderr, "Couldn't read vertex program 'Earth.vp'\n");
174 if(!_shl->readFragmentProgram("Earth.fp"))
175 fprintf(stderr, "Couldn't read fragment program 'Earth.fp'\n");
177 _shl->addUniformVariable("EarthDay", 0);
178 _shl->addUniformVariable("EarthNight", 1);
179 _shl->addUniformVariable("EarthCloudGloss", 2);
180 _shl->addUniformVariable("season", 0.0f);
181 _shl->addUniformVariable("cos_time_0_2PI", -0.406652f);
182 _shl->addUniformVariable("sin_time_0_2PI", -0.913583f);
183 _shl->addUniformVariable("foo", -0.913583f);
185 cmat->addChunk(_shl);
186 cmat->addChunk(tex_earth);
187 cmat->addChunk(tex_earth_env);
188 cmat->addChunk(tex_earth_night);
189 cmat->addChunk(tex_earth_night_env);
190 cmat->addChunk(tex_earth_clouds);
191 cmat->addChunk(tex_earth_clouds_env);
193 // create root node
194 _scene = Node::create();
196 GeometryRefPtr geo = makeLatLongSphereGeo (100, 100, 1.0);
198 geo->setMaterial(cmat);
201 NodeRefPtr torus = Node::create();
203 torus->setCore(geo);
206 // add torus to scene
207 GroupRefPtr group = Group::create();
209 _scene->setCore(group);
210 _scene->addChild(torus);
212 return NodeTransitPtr(_scene);
215 // Initialize GLUT & OpenSG and set up the scene
216 int main(int argc, char **argv)
218 char *opt;
219 NodeRefPtr scene;
221 // OSG init
222 osgInit(argc,argv);
224 // GLUT init
225 int winid = setupGLUT(&argc, argv);
227 // open a new scope, because the pointers below should go out of scope
228 // before entering glutMainLoop.
229 // Otherwise OpenSG will complain about objects being alive after shutdown.
232 // the connection between this client and the servers
233 MultiDisplayWindowRefPtr mwin = MultiDisplayWindow::create();
235 // evaluate params
236 for(int a=1 ; a<argc ; ++a)
238 if(argv[a][0] == '-')
240 switch(argv[a][1])
242 case 'm': mwin->setConnectionType("Multicast");
243 std::cout << "Connection type set to Multicast"
244 << std::endl;
245 break;
246 case 'p': mwin->setConnectionType("SockPipeline");
247 std::cout << "Connection type set to SockPipeline"
248 << std::endl;
249 break;
250 case 'i': opt = argv[a][2] ? argv[a]+2 : argv[++a];
251 if(opt != argv[argc])
252 mwin->setConnectionInterface(opt);
253 break;
254 case 'a': opt = argv[a][2] ? argv[a]+2 : argv[++a];
255 if(opt != argv[argc])
256 mwin->setServiceAddress(opt);
257 break;
258 case 'f': opt = argv[a][2] ? argv[a]+2 : argv[++a];
259 if(opt != argv[argc])
260 scene = SceneFileHandler::the()->read(opt, 0);
261 break;
262 case 'x': opt = argv[a][2] ? argv[a]+2 : argv[++a];
263 if(opt != argv[argc])
264 mwin->setHServers(atoi(opt));
265 break;
266 case 'y': opt = argv[a][2] ? argv[a]+2 : argv[++a];
267 if(opt != argv[argc])
268 mwin->setVServers(atoi(opt));
269 break;
270 default: std::cout << argv[0]
271 << " -m"
272 << " -p"
273 << " -i interface"
274 << " -f file"
275 << " -x horizontal server cnt"
276 << " -y vertical server cnt"
277 << std::endl;
278 return 0;
281 else
283 printf("%s\n",argv[a]);
284 mwin->editMFServers()->push_back(argv[a]);
288 // dummy size for navigator
289 mwin->setSize(300,300);
291 // create default scene
292 if(scene == NULL)
293 scene = createScene();
295 if(scene == NULL)
296 scene = makeTorus(.5, 2, 16, 16);
298 commitChanges();
300 // create the SimpleSceneManager helper
301 mgr = SimpleSceneManager::create();
303 // tell the manager what to manage
304 mgr->setWindow(mwin );
305 mgr->setRoot (scene);
307 // show the whole scene
308 mgr->showAll();
310 // initialize window
311 mwin->init();
314 // GLUT main loop
315 glutMainLoop();
317 return 0;
321 // GLUT callback functions
324 // redraw the window
325 void display(void)
327 static Real32 speed = 10000.0f;
328 static Real32 t = glutGet(GLUT_ELAPSED_TIME);
329 static Real32 t2 = 0.0;
331 Real32 td = glutGet(GLUT_ELAPSED_TIME) - t;
333 if(td > speed)
334 t = glutGet(GLUT_ELAPSED_TIME);
336 if(_animation)
338 t2 = (2 * OSG::Pi / speed) * td;
340 _shl->updateUniformVariable("cos_time_0_2PI", osgCos(t2));
341 _shl->updateUniformVariable("sin_time_0_2PI", osgSin(t2));
344 OSG::Thread::getCurrentChangeList()->commitChanges();
346 // redraw the cluster window
347 mgr->redraw();
348 // clear change list. If you don't clear the changelist,
349 // then the same changes will be transmitted a second time
350 // in the next frame.
351 OSG::Thread::getCurrentChangeList()->clear();
352 // clear local navigation window
353 glClear(GL_COLOR_BUFFER_BIT);
354 glutSwapBuffers();
357 // react to size changes
358 void reshape(int w, int h)
360 glutPostRedisplay();
363 // react to mouse button presses
364 void mouse(int button, int state, int x, int y)
366 if (state)
367 mgr->mouseButtonRelease(button, x, y);
368 else
369 mgr->mouseButtonPress(button, x, y);
370 glutPostRedisplay();
373 // react to mouse motions with pressed buttons
374 void motion(int x, int y)
376 mgr->mouseMove(x, y);
377 glutPostRedisplay();
380 // react to keys
381 void keyboard(unsigned char k, int x, int y)
383 static Real32 season = 0.0f;
385 switch(k)
387 case 27:
389 OSG::osgExit();
390 exit(0);
392 break;
393 case 's':
394 if(season < 0.435)
395 season += 0.01;
397 _shl->updateUniformVariable("season", season);
399 break;
400 case 'S':
401 if(season > -0.435)
402 season -= 0.01;
404 _shl->updateUniformVariable("season", season);
405 break;
406 case 'a':
407 _animation = 1 - _animation;
408 break;
412 // setup the GLUT library which handles the windows for us
413 int setupGLUT(int *argc, char *argv[])
415 glutInit(argc, argv);
416 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
418 int winid = glutCreateWindow("OpenSG");
420 glutReshapeFunc(reshape);
421 glutDisplayFunc(display);
422 glutMouseFunc(mouse);
423 glutMotionFunc(motion);
424 glutKeyboardFunc(keyboard);
426 glutIdleFunc(display);
428 return winid;