changed: gcc8 base update
[opensg.git] / Source / System / NodeCores / Drawables / Nurbs / testRationalSurfaceRender.cpp
blob45a47fdf9b2aa090e65ea9c0fc2caab63d1dffc4
1 // OpenSG NURBS example: testRationalSurfaceRender.cpp
2 //
3 // Shows how to render rational NURBS surfaces
4 //
5 // In OpenSG, similarly to OpenGL and OpenInventor rational
6 // control points are expected in homogenious coordinates
7 // (as opposed to Euclidian coordinates) that is a rational
8 // control point is [xw yw zw w] for surfaces, and
9 // [xw yw w] for trimming curves where [x y z] (or [x y]) are
10 // the Euclidian coordinates of the control point.
12 // Although this is not enforced, negative weights are
13 // not allowed, if a surface/curve has negative weights
14 // the behaviour of the tessellator is undefined.
16 // Zero weights are allowed, but only for inner control points.
17 // In other words, the first and last control points of a trimming
18 // curve (or the four corner control points of a surface) must all
19 // have positive weights.
21 // Press the keys '1', '2' and '3' in order to switch between
22 // the different example objects. Note that especially in the
23 // case of the torus and the teapot, tessellation takes some
24 // time so expect some delay when switching to the objects for
25 // the first time.
27 #include "OSGGLUT.h"
28 #include "OSGConfig.h"
29 #include "OSGSimpleSceneManager.h"
30 #include "OSGSimpleMaterial.h"
31 #include "OSGGLUTWindow.h"
32 #include "OSGSolidBackground.h"
33 #include "OSGSurface.h"
34 #include "OSGSwitch.h"
35 #include "OSGCoredNodePtr.h"
36 #include "OSGSceneFileHandler.h"
39 OSG::SimpleSceneManagerRefPtr g_mgr = NULL;
40 OSG::NodeRefPtr g_scene = NULL;
41 std::vector<OSG::Surface *> g_teapotSurfaces;
42 std::vector<OSG::Surface *> g_torusSurfaces;
43 std::vector<OSG::Surface *> g_cylinderSurfaces;
44 std::vector<OSG::Surface *> *g_currentSurfaces;
46 // redraw the window
47 void display(void)
49 // render
50 g_mgr->redraw();
54 // react to size changes
55 void reshape(int w, int h)
57 g_mgr->resize(w,h);
58 glutPostRedisplay();
61 // react to mouse button presses
62 void mouse(int button, int state, int x, int y)
64 if (state)
65 g_mgr->mouseButtonRelease(button, x, y);
66 else
67 g_mgr->mouseButtonPress(button, x, y);
69 glutPostRedisplay();
72 // react to mouse motions with pressed buttons
73 void motion(int x, int y)
75 g_mgr->mouseMove(x, y);
76 glutPostRedisplay();
80 void setModel(OSG::Int32 which)
82 OSG::Switch *s = dynamic_cast<OSG::Switch *>(g_scene->getCore());
83 s->setChoice(which);
85 switch(which)
87 case 0: g_currentSurfaces = &g_teapotSurfaces;
88 break;
90 case 1: g_currentSurfaces = &g_torusSurfaces;
91 break;
93 case 2: g_currentSurfaces = &g_cylinderSurfaces;
94 break;
96 default: std::cerr << "setModel [" << which << "] out of range."
97 << std::endl;
98 break;
101 if(g_mgr != NULL)
102 g_mgr->showAll();
105 // react to keys
106 void keyboard(unsigned char k, int, int)
108 switch(k)
110 case 27: g_mgr = NULL;
111 g_scene = NULL;
112 exit(1);
113 case 'y':
114 case 'z':
115 glPolygonMode( GL_FRONT_AND_BACK, GL_POINT);
116 std::cerr << "PolygonMode: Point." << std::endl;
117 break;
118 case 'x': glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
119 std::cerr << "PolygonMode: Line." << std::endl;
120 break;
121 case 'c': glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
122 std::cerr << "PolygonMode: Fill." << std::endl;
123 break;
124 case '1': std::cerr<<"Model: teapot."<<std::endl;
125 setModel(0);
126 break;
127 case '2': std::cerr<<"Model: torus."<<std::endl;
128 setModel(1);
129 break;
130 case '3': std::cerr<<"Model: trimmed cylinder."<<std::endl;
131 setModel(2);
132 break;
133 case 'o': OSG::SceneFileHandler::the()->write(g_scene, "out.osb");
134 break;
136 case 'f': for(OSG::UInt32 i = 0; i < g_currentSurfaces->size(); ++i)
138 g_currentSurfaces->at(i)->setError(
139 2 * g_currentSurfaces->at(i)->getError());
141 break;
143 case 'g': for(OSG::UInt32 i = 0; i < g_currentSurfaces->size(); ++i)
145 g_currentSurfaces->at(i)->setError(
146 g_currentSurfaces->at(i)->getError() / 2);
148 break;
150 default: break;
154 // Helper function to create an untrimmed rational OSG::Surface Core+Node
155 // from the controlpoints, dimensions in U & V,
156 // knotvectors in U & V and the desired error and material.
157 OSG::NodeTransitPtr makeSurface(const int numcps, const float xyzw[][4],
158 const int dimU, const int dimV,
159 const int numknotsU, const float *knotsU,
160 const int numknotsV, const float *knotsV,
161 const float error, OSG::Material *mat)
163 OSG::SurfaceRefPtr surface;
164 OSG::NodeTransitPtr ret =
165 OSG::makeCoredNode<OSG::Surface>(&surface);
166 OSG::GeoPnt4fPropertyRefPtr cps = OSG::GeoPnt4fProperty::create();
167 int i;
169 cps->clear();
170 for (i = 0; i < numcps; ++i)
172 cps->editField().push_back(OSG::Pnt4f(xyzw[i][0], xyzw[i][1],
173 xyzw[i][2], xyzw[i][3]));
176 // let's clear the trimming
177 surface->removeCurves();
178 // set up dimensions and knot vectors:
179 surface->setDimU( dimU );
180 surface->setDimV( dimV );
181 surface->editMFKnotsU()->clear();
182 for (i = 0; i < numknotsU; ++i)
184 surface->editMFKnotsU()->push_back(knotsU[i]);
187 surface->editMFKnotsV()->clear();
188 for (i = 0; i < numknotsV; ++i)
190 surface->editMFKnotsV()->push_back(knotsV[i]);
192 // set control points
193 surface->setControlPoints(cps);
194 // set error
195 surface->setError(error);
196 // and finally set the material
197 surface->setMaterial(mat);
199 return ret;
202 // Helper function to add a polynomial trimcurve to an OSG::Surface NodeCore
203 void addTrimCurve(OSG::Surface *surf, const int numcps, const float xy[][2],
204 const int dim, const int numknots, const float *knots,
205 bool startnewloop = false)
207 std::vector<OSG::Real64> knotv;
208 std::vector<OSG::Pnt2f> cps;
209 int i;
210 for (i = 0; i < numcps; ++i)
212 cps.push_back(OSG::Pnt2f(xy[i][0], xy[i][1]));
214 for (i = 0; i < numknots; ++i)
216 knotv.push_back(knots[i]);
219 surf->addCurve(dim, knotv, cps, startnewloop);
222 // Helper function to add a rational trimcurve to an OSG::Surface NodeCore
223 void addTrimCurve(OSG::Surface *surf, const int numcps, const float xyw[][3],
224 const int dim, const int numknots, const float *knots,
225 bool startnewloop = false)
227 std::vector<OSG::Real64> knotv;
228 std::vector<OSG::Pnt3f> cps;
229 int i;
230 for (i = 0; i < numcps; ++i)
232 cps.push_back(OSG::Pnt3f(xyw[i][0], xyw[i][1], xyw[i][2]));
234 for (i = 0; i < numknots; ++i)
236 knotv.push_back(knots[i]);
239 surf->addCurve(dim, knotv, cps, startnewloop);
243 // This function creates the classic Utah teapot from 4 NURBS
244 // surfaces: one surface each for the lid, body, handle and spout.
245 // The "classic" representation is using 18 rational Bezier patches,
246 // but in order to show the construction of more complex surfaces
247 // these have been combined into as few NURBS surfaces as possible.
248 OSG::NodeTransitPtr makeTeapot(void)
250 OSG::SimpleMaterialRefPtr teapotmat = OSG::SimpleMaterial::create();
252 teapotmat->setDiffuse( OSG::Color3f(0.8, 0.8, 0.8));
253 teapotmat->setAmbient( OSG::Color3f(0.2, 0.2, 0.2));
254 teapotmat->setEmission( OSG::Color3f(0.02, 0.02, 0.02) );
255 teapotmat->setSpecular( OSG::Color3f(0.78, 0.78, 0.78) );
256 teapotmat->setShininess( 128 );
258 OSG::NodeTransitPtr teapotroot = OSG::makeCoredNode<OSG::Group>();
259 float knots11[11] = {0, 0, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 1};
260 float knots14[14] = {0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3};
261 float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
262 float lidcps[35][4] = {
263 { 0.0000, 4.0000, 0.0000, 1.0000},
264 { 0.0000, 4.0000, 0.8000, 1.0000},
265 { 0.0000, 3.6000, 0.0000, 1.0000},
266 { 0.0000, 3.4000, 0.2000, 1.0000},
267 { 0.0000, 3.2000, 0.4000, 1.0000},
268 { 0.0000, 3.2000, 1.3000, 1.0000},
269 { 0.0000, 3.0000, 1.3000, 1.0000},
271 {-0.0000, 0.0000, 0.0000, 0.0000},
272 {-0.8000, 0.0000, 0.0000, 0.0000},
273 {-0.0000, 0.0000, 0.0000, 0.0000},
274 {-0.2000, 0.0000, 0.0000, 0.0000},
275 {-0.4000, 0.0000, 0.0000, 0.0000},
276 {-1.3000, 0.0000, 0.0000, 0.0000},
277 {-1.3000, 0.0000, 0.0000, 0.0000},
279 { 0.0000, 4.0000,-0.0000, 1.0000},
280 { 0.0000, 4.0000,-0.8000, 1.0000},
281 { 0.0000, 3.6000,-0.0000, 1.0000},
282 { 0.0000, 3.4000,-0.2000, 1.0000},
283 { 0.0000, 3.2000,-0.4000, 1.0000},
284 { 0.0000, 3.2000,-1.3000, 1.0000},
285 { 0.0000, 3.0000,-1.3000, 1.0000},
287 { 0.0000, 0.0000, 0.0000, 0.0000},
288 { 0.8000, 0.0000, 0.0000, 0.0000},
289 { 0.0000, 0.0000, 0.0000, 0.0000},
290 { 0.2000, 0.0000, 0.0000, 0.0000},
291 { 0.4000, 0.0000, 0.0000, 0.0000},
292 { 1.3000, 0.0000, 0.0000, 0.0000},
293 { 1.3000, 0.0000, 0.0000, 0.0000},
295 { 0.0000, 4.0000, 0.0000, 1.0000},
296 { 0.0000, 4.0000, 0.8000, 1.0000},
297 { 0.0000, 3.6000, 0.0000, 1.0000},
298 { 0.0000, 3.4000, 0.2000, 1.0000},
299 { 0.0000, 3.2000, 0.4000, 1.0000},
300 { 0.0000, 3.2000, 1.3000, 1.0000},
301 { 0.0000, 3.0000, 1.3000, 1.0000},
303 OSG::NodeRefPtr lid = makeSurface(35, lidcps, 2, 3, 8, knots_circle,
304 11, knots11, 0.005, teapotmat);
306 g_teapotSurfaces.push_back(dynamic_cast<OSG::Surface *>(lid->getCore()));
308 float bodycps[50][4] = {
309 { 0.0000, 3.0000, 1.4000, 1.0000},
310 { 0.0000, 3.1750, 1.3375, 1.0000},
311 { 0.0000, 3.1750, 1.4375, 1.0000},
312 { 0.0000, 3.0000, 1.5000, 1.0000},
313 { 0.0000, 2.3000, 1.7500, 1.0000},
314 { 0.0000, 1.6000, 2.0000, 1.0000},
315 { 0.0000, 1.0000, 2.0000, 1.0000},
316 { 0.0000, 0.4000, 2.0000, 1.0000},
317 { 0.0000, 0.2000, 1.5000, 1.0000},
318 { 0.0000, 0.0000, 1.5000, 1.0000},
320 {-1.4000, 0.0000, 0.0000, 0.0000},
321 {-1.3375, 0.0000, 0.0000, 0.0000},
322 {-1.4375, 0.0000, 0.0000, 0.0000},
323 {-1.5000, 0.0000, 0.0000, 0.0000},
324 {-1.7500, 0.0000, 0.0000, 0.0000},
325 {-2.0000, 0.0000, 0.0000, 0.0000},
326 {-2.0000, 0.0000, 0.0000, 0.0000},
327 {-2.0000, 0.0000, 0.0000, 0.0000},
328 {-1.5000, 0.0000, 0.0000, 0.0000},
329 {-1.5000, 0.0000, 0.0000, 0.0000},
331 { 0.0000, 3.0000,-1.4000, 1.0000},
332 { 0.0000, 3.1750,-1.3375, 1.0000},
333 { 0.0000, 3.1750,-1.4375, 1.0000},
334 { 0.0000, 3.0000,-1.5000, 1.0000},
335 { 0.0000, 2.3000,-1.7500, 1.0000},
336 { 0.0000, 1.6000,-2.0000, 1.0000},
337 { 0.0000, 1.0000,-2.0000, 1.0000},
338 { 0.0000, 0.4000,-2.0500, 1.0000},
339 { 0.0000, 0.2000,-1.5000, 1.0000},
340 { 0.0000, 0.0000,-1.5000, 1.0000},
342 { 1.4000, 0.0000, 0.0000, 0.0000},
343 { 1.3375, 0.0000, 0.0000, 0.0000},
344 { 1.4375, 0.0000, 0.0000, 0.0000},
345 { 1.5000, 0.0000, 0.0000, 0.0000},
346 { 1.7500, 0.0000, 0.0000, 0.0000},
347 { 2.0000, 0.0000, 0.0000, 0.0000},
348 { 2.0000, 0.0000, 0.0000, 0.0000},
349 { 2.0000, 0.0000, 0.0000, 0.0000},
350 { 1.5000, 0.0000, 0.0000, 0.0000},
351 { 1.5000, 0.0000, 0.0000, 0.0000},
353 { 0.0000, 3.0000, 1.4000, 1.0000},
354 { 0.0000, 3.1750, 1.3375, 1.0000},
355 { 0.0000, 3.1750, 1.4375, 1.0000},
356 { 0.0000, 3.0000, 1.5000, 1.0000},
357 { 0.0000, 2.3000, 1.7500, 1.0000},
358 { 0.0000, 1.6000, 2.0000, 1.0000},
359 { 0.0000, 1.0000, 2.0000, 1.0000},
360 { 0.0000, 0.4000, 2.0000, 1.0000},
361 { 0.0000, 0.2000, 1.5000, 1.0000},
362 { 0.0000, 0.0000, 1.5000, 1.0000},
365 OSG::NodeRefPtr body = makeSurface(50, bodycps, 2, 3, 8, knots_circle,
366 14, knots14, 0.005, teapotmat);
368 g_teapotSurfaces.push_back(dynamic_cast<OSG::Surface *>(body->getCore()));
370 float handlecps[35][4] = {
371 { 1.5000, 2.8000, 0.0000, 1.0000},
372 { 2.5000, 2.8000, 0.0000, 1.0000},
373 { 3.0000, 2.8000, 0.0000, 1.0000},
374 { 3.0000, 2.2000, 0.0000, 1.0000},
375 { 3.0000, 1.6000, 0.0000, 1.0000},
376 { 2.6500, 1.0500, 0.0000, 1.0000},
377 { 1.9000, 0.6000, 0.0000, 1.0000},
379 { 0.0000, 0.0000, 0.3000, 0.0000},
380 { 0.0000, 0.0000, 0.3000, 0.0000},
381 { 0.0000, 0.0000, 0.3000, 0.0000},
382 { 0.0000, 0.0000, 0.3000, 0.0000},
383 { 0.0000, 0.0000, 0.3000, 0.0000},
384 { 0.0000, 0.0000, 0.3000, 0.0000},
385 { 0.0000, 0.0000, 0.3000, 0.0000},
387 { 1.6000, 2.5000, 0.0000, 1.0000},
388 { 2.3000, 2.5000, 0.0000, 1.0000},
389 { 2.7000, 2.5000, 0.0000, 1.0000},
390 { 2.7000, 2.2000, 0.0000, 1.0000},
391 { 2.7000, 1.9000, 0.0000, 1.0000},
392 { 2.5000, 1.5000, 0.0000, 1.0000},
393 { 2.0000, 1.0000, 0.0000, 1.0000},
395 { 0.0000, 0.0000,-0.3000, 0.0000},
396 { 0.0000, 0.0000,-0.3000, 0.0000},
397 { 0.0000, 0.0000,-0.3000, 0.0000},
398 { 0.0000, 0.0000,-0.3000, 0.0000},
399 { 0.0000, 0.0000,-0.3000, 0.0000},
400 { 0.0000, 0.0000,-0.3000, 0.0000},
401 { 0.0000, 0.0000,-0.3000, 0.0000},
403 { 1.5000, 2.8000, 0.0000, 1.0000},
404 { 2.5000, 2.8000, 0.0000, 1.0000},
405 { 3.0000, 2.8000, 0.0000, 1.0000},
406 { 3.0000, 2.2000, 0.0000, 1.0000},
407 { 3.0000, 1.6000, 0.0000, 1.0000},
408 { 2.6500, 1.0500, 0.0000, 1.0000},
409 { 1.9000, 0.6000, 0.0000, 1.0000},
412 OSG::NodeRefPtr handle = makeSurface(35, handlecps, 2, 3, 8, knots_circle,
413 11, knots11, 0.005, teapotmat);
415 g_teapotSurfaces.push_back(dynamic_cast<OSG::Surface *>(handle->getCore()));
417 float spoutcps[35][4] = {
418 {-1.7000, 0.6000, 0.0000, 1.0000},
419 {-3.1000, 0.9000, 0.0000, 1.0000},
420 {-2.4000, 2.6000, 0.0000, 1.0000},
421 {-3.3000, 3.0000, 0.0000, 1.0000},
422 {-3.5250, 3.1250, 0.0000, 1.0000},
423 {-3.4500, 3.1500, 0.0000, 1.0000},
424 {-3.2000, 3.0000, 0.0000, 1.0000},
426 { 0.0000, 0.0000, 0.6600, 0.0000},
427 { 0.0000, 0.0000, 0.6600, 0.0000},
428 { 0.0000, 0.0000, 0.2500, 0.0000},
429 { 0.0000, 0.0000, 0.2500, 0.0000},
430 { 0.0000, 0.0000, 0.2500, 0.0000},
431 { 0.0000, 0.0000, 0.1500, 0.0000},
432 { 0.0000, 0.0000, 0.1500, 0.0000},
434 {-1.7000, 1.7000, 0.0000, 1.0000},
435 {-2.6000, 1.7000, 0.0000, 1.0000},
436 {-2.3000, 2.6000, 0.0000, 1.0000},
437 {-2.7000, 3.0000, 0.0000, 1.0000},
438 {-2.8000, 3.1000, 0.0000, 1.0000},
439 {-2.9000, 3.1000, 0.0000, 1.0000},
440 {-2.8000, 3.0000, 0.0000, 1.0000},
442 { 0.0000, 0.0000,-0.6600, 0.0000},
443 { 0.0000, 0.0000,-0.6600, 0.0000},
444 { 0.0000, 0.0000,-0.2500, 0.0000},
445 { 0.0000, 0.0000,-0.2500, 0.0000},
446 { 0.0000, 0.0000,-0.2500, 0.0000},
447 { 0.0000, 0.0000,-0.1500, 0.0000},
448 { 0.0000, 0.0000,-0.1500, 0.0000},
450 {-1.7000, 0.6000, 0.0000, 1.0000},
451 {-3.1000, 0.9000, 0.0000, 1.0000},
452 {-2.4000, 2.6000, 0.0000, 1.0000},
453 {-3.3000, 3.0000, 0.0000, 1.0000},
454 {-3.5250, 3.1250, 0.0000, 1.0000},
455 {-3.4500, 3.1500, 0.0000, 1.0000},
456 {-3.2000, 3.0000, 0.0000, 1.0000},
458 OSG::NodeRefPtr spout = makeSurface(35, spoutcps, 2, 3, 8, knots_circle,
459 11, knots11, 0.005, teapotmat);
461 g_teapotSurfaces.push_back(dynamic_cast<OSG::Surface *>(spout->getCore()));
463 teapotroot->addChild(lid);
464 teapotroot->addChild(body);
465 teapotroot->addChild(handle);
466 teapotroot->addChild(spout);
468 return teapotroot;
471 // This function creates a torus from a single NURBS surface
472 // using only 25 control points (of which 12 are unique).
473 // Similarly to the teapot, this uses the half-circle
474 // constructed from 3 control points (of which the middle point
475 // is infinite) which is then mirrored to form a full circle.
476 // (See the NURBS book [Piegl and Tiller], pp. 296, Ex7.1 (Figure 7.15)
477 // for details on the half-circle.)
478 OSG::NodeTransitPtr makeTorus(void)
480 OSG::SimpleMaterialRefPtr torusmat = OSG::SimpleMaterial::create();
482 torusmat->setDiffuse( OSG::Color3f(1.0, 0.0, 0.2));
483 torusmat->setAmbient( OSG::Color3f(0.2, 0.2, 0.2));
484 torusmat->setEmission( OSG::Color3f(0.02, 0.02, 0.02) );
485 torusmat->setSpecular( OSG::Color3f(0.78, 0.78, 0.78) );
486 torusmat->setShininess( 128 );
488 float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
489 float toruscps[25][4] = {
490 { 1.00, 0, .75, 1}, //
491 { .25, 0, 0, 0}, //
492 { 1.00, 0, 1.25, 1}, //
493 { -.25, 0, 0, 0}, //
494 { 1.00, 0, .75, 1},
495 { 0, 1.00, 0, 0}, //
496 { 0, .25, 0, 0}, //
497 { 0, 1.00, 0, 0},
498 { 0, -.25, 0, 0}, //
499 { 0, 1.00, 0, 0},
500 {-1.00, 0, .75, 1}, //
501 { -.25, 0, 0, 0}, //
502 {-1.00, 0, 1.25, 1}, //
503 { .25, 0, 0, 0}, //
504 {-1.00, 0, .75, 1},
505 { 0, -1.00, 0, 0}, //
506 { 0, -.25, 0, 0},
507 { 0, -1.00, 0, 0},
508 { 0, .25, 0, 0},
509 { 0, -1.00, 0, 0},
510 { 1.00, 0, .75, 1},
511 { .25, 0, 0, 0},
512 { 1.00, 0, 1.25, 1},
513 { -.25, 0, 0, 0},
514 { 1.00, 0, .75, 1},
517 OSG::NodeTransitPtr torus = makeSurface(25, toruscps, 2, 2, 8, knots_circle,
518 8, knots_circle, 0.005, torusmat);
519 g_torusSurfaces.push_back(dynamic_cast<OSG::Surface *>(torus->getCore()));
521 return torus;
524 // This function creates a cylinder similarly to the teapot
525 // and the torus above. This time the cylinder is trimmed with
526 // a circle defined by 9 square-based control points to show
527 // an example of defining a circle without using infinite control
528 // points (see [Piegl and Tiller], pp. 299, Ex7.2 (Figure 7.16)) as
529 // well as to show how to define a rational trimming curve.
530 OSG::NodeTransitPtr makeTrimmedCylinder(void)
532 OSG::SimpleMaterialRefPtr cylmat = OSG::SimpleMaterial::create();
534 cylmat->setDiffuse( OSG::Color3f(0.0, 0.8, 0.7));
535 cylmat->setAmbient( OSG::Color3f(0.2, 0.2, 0.2));
536 cylmat->setEmission( OSG::Color3f(0.02, 0.02, 0.02) );
537 cylmat->setSpecular( OSG::Color3f(0.78, 0.78, 0.78) );
538 cylmat->setShininess( 128 );
540 float knots4[4] = {0, 0, 1, 1};
541 float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
542 float knots_outertrim[7] = {0, 0, 1, 2, 3, 4, 4};
543 float knots_trimcircle[12] = {0, 0, 0, 0.25, 0.25, 0.5,
544 0.5, 0.75, 0.75, 1, 1, 1};
545 float cylcps[10][4] = {
546 { 1.00, 0, -.50, 1},
547 { 1.00, 0, .50, 1},
548 { 0, 1.00, 0, 0},
549 { 0, 1.00, 0, 0},
550 {-1.00, 0, -.50, 1},
551 {-1.00, 0, .50, 1},
552 { 0, -1.00, 0, 0},
553 { 0, -1.00, 0, 0},
554 { 1.00, 0, -.50, 1},
555 { 1.00, 0, .50, 1},
557 float outertrim_cps[5][2] = {
558 {0, 0},
559 {1, 0},
560 {1, 1},
561 {0, 1},
562 {0, 0},
564 float trimcircle_cps[9][3] = {
565 {0.541667, 0.5, 1},
566 {0.383016, 0.235702, 0.707107},
567 {0.5, 0.333333, 1},
568 {0.324091, 0.235702, 0.707107},
569 {0.458333, 0.5, 1},
570 {0.324091, 0.471405, 0.707107},
571 {0.5, 0.666667, 1},
572 {0.383016, 0.471405, 0.707107},
573 {0.541667, 0.5, 1},
575 OSG::NodeTransitPtr cylnode = makeSurface(10, cylcps, 2, 1, 8, knots_circle,
576 4, knots4, 0.001, cylmat);
577 OSG::Surface *s = dynamic_cast<OSG::Surface *>(cylnode->getCore());
578 // add outer trimming around the domain
579 addTrimCurve(s, 5, outertrim_cps, 1, 7, knots_outertrim, true);
580 // add inside circle trimming
581 addTrimCurve(s, 9, trimcircle_cps, 2, 12, knots_trimcircle, true);
583 g_cylinderSurfaces.push_back(
584 dynamic_cast<OSG::Surface *>(cylnode->getCore()));
586 return cylnode;
589 OSG::NodeTransitPtr makeScene(void)
591 OSG::NodeTransitPtr root = OSG::makeCoredNode<OSG::Switch>();
593 root->addChild(makeTeapot());
594 root->addChild(makeTorus());
595 root->addChild(makeTrimmedCylinder());
597 return root;
600 int main(int argc, char **argv)
602 printf("Press the keys '1', '2' and '3' in order to switch between "
603 "the different example objects.\n");
605 OSG::osgInit(argc,argv);
606 // GLUT init
607 glutInit(&argc, argv);
608 glutInitWindowSize(800,600);
609 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
611 int winid = glutCreateWindow("OpenSG");
613 glutReshapeFunc(reshape);
614 glutDisplayFunc(display);
615 glutIdleFunc(display);
616 glutMouseFunc(mouse);
617 glutMotionFunc(motion);
618 glutKeyboardFunc(keyboard);
621 OSG::GLUTWindowRefPtr gwin = OSG::GLUTWindow::create();
622 gwin->setGlutId(winid);
623 gwin->init();
625 // create the scene
626 g_scene = makeScene();
627 setModel(0);
629 if ( g_scene == NULL )
631 std::cerr<<"makeScene returned NullFC, exiting..."<<std::endl;
632 return -1;
635 // create the SimpleSceneManager helper
636 g_mgr = OSG::SimpleSceneManager::create();
638 // create the window and initial camera/viewport
639 g_mgr->setWindow( gwin );
640 // tell the manager what to manage
641 g_mgr->setRoot ( g_scene );
643 // show the whole scene
644 g_mgr->showAll();
645 g_mgr->redraw();
646 OSG::SolidBackgroundRefPtr bgr = OSG::SolidBackground::create();
647 bgr->setColor(OSG::Color3f( 0.7, 0.7, 0.7 ));
648 g_mgr->getWindow()->getPort(0)->setBackground(bgr);
651 // GLUT main loop
652 glutMainLoop();
654 return 0;