1 // OpenSG Tutorial Example: Minimalistic OpenSG cluster client program
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
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
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
25 #ifdef OSG_BUILD_ACTIVE
26 // GLUT is used for window handling
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>
48 #include <OSGChunkMaterial.h>
49 #include <OSGMaterialChunk.h>
50 #include <OSGTextureObjChunk.h>
51 #include <OSGTextureEnvChunk.h>
52 #include <OSGSHLChunk.h>
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>
83 // The SimpleSceneManager to manage simple applications
84 SimpleSceneManagerRefPtr mgr
;
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
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
106 NodeTransitPtr
createScene(void)
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
);
194 _scene
= Node::create();
196 GeometryRefPtr geo
= makeLatLongSphereGeo (100, 100, 1.0);
198 geo
->setMaterial(cmat
);
201 NodeRefPtr torus
= Node::create();
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
)
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();
236 for(int a
=1 ; a
<argc
; ++a
)
238 if(argv
[a
][0] == '-')
242 case 'm': mwin
->setConnectionType("Multicast");
243 std::cout
<< "Connection type set to Multicast"
246 case 'p': mwin
->setConnectionType("SockPipeline");
247 std::cout
<< "Connection type set to SockPipeline"
250 case 'i': opt
= argv
[a
][2] ? argv
[a
]+2 : argv
[++a
];
251 if(opt
!= argv
[argc
])
252 mwin
->setConnectionInterface(opt
);
254 case 'a': opt
= argv
[a
][2] ? argv
[a
]+2 : argv
[++a
];
255 if(opt
!= argv
[argc
])
256 mwin
->setServiceAddress(opt
);
258 case 'f': opt
= argv
[a
][2] ? argv
[a
]+2 : argv
[++a
];
259 if(opt
!= argv
[argc
])
260 scene
= SceneFileHandler::the()->read(opt
, 0);
262 case 'x': opt
= argv
[a
][2] ? argv
[a
]+2 : argv
[++a
];
263 if(opt
!= argv
[argc
])
264 mwin
->setHServers(atoi(opt
));
266 case 'y': opt
= argv
[a
][2] ? argv
[a
]+2 : argv
[++a
];
267 if(opt
!= argv
[argc
])
268 mwin
->setVServers(atoi(opt
));
270 default: std::cout
<< argv
[0]
275 << " -x horizontal server cnt"
276 << " -y vertical server cnt"
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
293 scene
= createScene();
296 scene
= makeTorus(.5, 2, 16, 16);
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
321 // GLUT callback functions
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
;
334 t
= glutGet(GLUT_ELAPSED_TIME
);
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
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
);
357 // react to size changes
358 void reshape(int w
, int h
)
363 // react to mouse button presses
364 void mouse(int button
, int state
, int x
, int y
)
367 mgr
->mouseButtonRelease(button
, x
, y
);
369 mgr
->mouseButtonPress(button
, x
, y
);
373 // react to mouse motions with pressed buttons
374 void motion(int x
, int y
)
376 mgr
->mouseMove(x
, y
);
381 void keyboard(unsigned char k
, int x
, int y
)
383 static Real32 season
= 0.0f
;
397 _shl
->updateUniformVariable("season", season
);
404 _shl
->updateUniformVariable("season", season
);
407 _animation
= 1 - _animation
;
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
);