fixed: let the material fill the override chunk block
[opensg.git] / Source / System / Text / testTextPixmap.cpp
blobcc217845ee44af65b2d15ee109a00f72f3716fa8
1 #include "OSGGLUT.h"
2 #include "OSGConfig.h"
3 #include "OSGSimpleGeometry.h"
4 #include "OSGGLUTWindow.h"
5 #include "OSGSimpleSceneManager.h"
6 #include "OSGBaseFunctions.h"
7 #include "OSGTransform.h"
8 #include "OSGGroup.h"
9 #include "OSGImage.h"
10 #include "OSGMaterialChunk.h"
11 #include "OSGTextureTransformChunk.h"
12 #include "OSGSimpleStatisticsForeground.h"
13 #include "OSGSolidBackground.h"
14 #include "OSGGeometry.h"
15 #include "OSGTypedGeoIntegralProperty.h"
17 #include "OSGTextPixmapFace.h"
18 #include "OSGTextPixmapGlyph.h"
19 #include "OSGTextLayoutParam.h"
20 #include "OSGTextLayoutResult.h"
21 #include "OSGTextFaceFactory.h"
23 // Activate the OpenSG namespace
24 using namespace std;
26 // The SimpleSceneManager to manage simple applications
27 OSG::SimpleSceneManagerRefPtr mgr;
29 OSG::NodeRecPtr scene;
31 OSG::SimpleStatisticsForegroundRecPtr statfg;
32 OSG::StatElemDesc<OSG::StatStringElem> familyDesc("family", "The font family");
33 OSG::StatElemDesc<OSG::StatStringElem> styleDesc("style", "The font style");
34 OSG::StatElemDesc<OSG::StatStringElem> majorAlignDesc("majorAlignment", "The major alignment");
35 OSG::StatElemDesc<OSG::StatStringElem> minorAlignDesc("minorAlignment", "The minor alignment");
36 OSG::StatElemDesc<OSG::StatStringElem> dirDesc("direction", "The direction (horizontal or vertical)");
37 OSG::StatElemDesc<OSG::StatStringElem> horiDirDesc("horizontal direction", "The horizontal direction (left-to-right or right-to-left)");
38 OSG::StatElemDesc<OSG::StatStringElem> vertDirDesc("vertical direction", "The vertical direction (top-to-bottom or bottom-to-top)");
40 OSG::TextPixmapFaceRefPtr face;
41 string family = "SANS";
42 vector<string> families;
43 OSG::TextFace::Style style = OSG::TextFace::STYLE_PLAIN;
44 OSG::TextLayoutParam layoutParam;
45 vector<string> lines;
47 int mainMenuID;
49 // forward declaration so we can have the interesting stuff upfront
50 int setupGLUT( int *argc, char *argv[] );
52 // Create the coordinate cross
53 OSG::NodeTransitPtr createCoordinateCross()
55 OSG::GeometryUnrecPtr geoPtr = OSG::Geometry::create();
57 OSG::GeoUInt8PropertyUnrecPtr typesPtr = OSG::GeoUInt8Property::create();
58 typesPtr->push_back(GL_LINES);
59 geoPtr->setTypes(typesPtr);
61 OSG::GeoUInt32PropertyUnrecPtr lensPtr = OSG::GeoUInt32Property::create();
62 lensPtr->push_back(6);
63 geoPtr->setLengths(lensPtr);
65 OSG::GeoPnt3fPropertyUnrecPtr posPtr = OSG::GeoPnt3fProperty::create();
66 posPtr->push_back(OSG::Vec3f(-0.1f, 0.f, 0.f));
67 posPtr->push_back(OSG::Vec3f(1.f, 0.f, 0.f));
68 posPtr->push_back(OSG::Vec3f(0.f, -0.1f, 0.f));
69 posPtr->push_back(OSG::Vec3f(0.f, 1.f, 0.f));
70 posPtr->push_back(OSG::Vec3f(0.f, 0.f, -0.1f));
71 posPtr->push_back(OSG::Vec3f(0.f, 0.f, 1.f));
72 geoPtr->setPositions(posPtr);
74 OSG::GeoColor3fPropertyUnrecPtr colorsPtr = OSG::GeoColor3fProperty::create();
75 colorsPtr->push_back(OSG::Color3f(1.f, 0.f, 0.f));
76 colorsPtr->push_back(OSG::Color3f(0.f, 1.f, 0.f));
77 colorsPtr->push_back(OSG::Color3f(0.f, 0.f, 1.f));
78 geoPtr->setColors(colorsPtr);
80 OSG::GeoUInt32PropertyUnrecPtr posIndicesPtr = OSG::GeoUInt32Property::create();
81 OSG::GeoUInt32PropertyUnrecPtr colIndicesPtr = OSG::GeoUInt32Property::create();
82 // X Axis
83 posIndicesPtr->push_back(0);
84 colIndicesPtr->push_back(0);
85 posIndicesPtr->push_back(1);
86 colIndicesPtr->push_back(0);
87 // Y Axis
88 posIndicesPtr->push_back(2);
89 colIndicesPtr->push_back(1);
90 posIndicesPtr->push_back(3);
91 colIndicesPtr->push_back(1);
92 // Z Axis
93 posIndicesPtr->push_back(4);
94 colIndicesPtr->push_back(2);
95 posIndicesPtr->push_back(5);
96 colIndicesPtr->push_back(2);
97 geoPtr->setIndex(posIndicesPtr, OSG::Geometry::PositionsIndex);
98 geoPtr->setIndex(colIndicesPtr, OSG::Geometry::ColorsIndex);
100 OSG::SimpleMaterialUnrecPtr matPtr = OSG::SimpleMaterial::create();
101 geoPtr->setMaterial(matPtr);
103 OSG::NodeTransitPtr nodePtr = OSG::Node::create();
104 nodePtr->setCore(geoPtr);
106 return nodePtr;
109 // Create the metrics
110 OSG::NodeTransitPtr createMetrics(OSG::TextFace *face, OSG::Real32 scale, const OSG::TextLayoutParam &layoutParam,
111 const OSG::TextLayoutResult &layoutResult)
113 OSG::GeometryUnrecPtr geoPtr = OSG::Geometry::create();
115 OSG::GeoUInt8PropertyUnrecPtr typesPtr = OSG::GeoUInt8Property::create();
116 geoPtr->setTypes(typesPtr);
118 OSG::GeoUInt32PropertyUnrecPtr lensPtr = OSG::GeoUInt32Property::create();
119 geoPtr->setLengths(lensPtr);
121 OSG::GeoPnt3fPropertyUnrecPtr posPtr = OSG::GeoPnt3fProperty::create();
122 geoPtr->setPositions(posPtr);
124 OSG::GeoColor3fPropertyUnrecPtr colorsPtr = OSG::GeoColor3fProperty::create();
125 colorsPtr->push_back(OSG::Color3f(0.f, 0.f, 1.f));
126 colorsPtr->push_back(OSG::Color3f(1.f, 0.f, 0.f));
127 colorsPtr->push_back(OSG::Color3f(0.f, 1.f, 0.f));
128 colorsPtr->push_back(OSG::Color3f(1.f, 1.f, 0.f));
129 geoPtr->setColors(colorsPtr);
131 OSG::GeoUInt32PropertyUnrecPtr posIndicesPtr = OSG::GeoUInt32Property::create();
132 geoPtr->setIndex(posIndicesPtr, OSG::Geometry::PositionsIndex);
133 OSG::GeoUInt32PropertyUnrecPtr colIndicesPtr = OSG::GeoUInt32Property::create();
134 geoPtr->setIndex(colIndicesPtr, OSG::Geometry::ColorsIndex);
136 OSG::UInt32 i, numGlyphs = layoutResult.getNumGlyphs();
137 for (i = 0; i < numGlyphs; ++i)
139 const OSG::TextGlyph &glyph = face->getGlyph(layoutResult.indices[i]);
140 typesPtr->push_back(GL_LINE_LOOP);
141 lensPtr->push_back(4);
142 const OSG::Vec2f &pos = layoutResult.positions[i];
143 OSG::Real32 left = pos.x() * scale;
144 OSG::Real32 right = (pos.x() + glyph.getWidth()) * scale;
145 OSG::Real32 top = pos.y() * scale;
146 OSG::Real32 bottom = (pos.y() - glyph.getHeight()) * scale;
147 OSG::UInt32 posOffset = posPtr->size();
148 posPtr->push_back(OSG::Vec3f(left, bottom, 0.f));
149 posPtr->push_back(OSG::Vec3f(right, bottom, 0.f));
150 posPtr->push_back(OSG::Vec3f(right, top, 0.f));
151 posPtr->push_back(OSG::Vec3f(left, top, 0.f));
152 posIndicesPtr->push_back(posOffset);
153 colIndicesPtr->push_back(0);
154 posIndicesPtr->push_back(posOffset + 1);
155 colIndicesPtr->push_back(0);
156 posIndicesPtr->push_back(posOffset + 2);
157 colIndicesPtr->push_back(0);
158 posIndicesPtr->push_back(posOffset + 3);
159 colIndicesPtr->push_back(0);
162 // Bounding box
163 OSG::Vec2f lowerLeft, upperRight;
164 face->calculateBoundingBox(layoutResult, lowerLeft, upperRight);
165 typesPtr->push_back(GL_LINE_LOOP);
166 lensPtr->push_back(4);
167 OSG::Real32 left = lowerLeft.x() * scale;
168 OSG::Real32 right = upperRight.x() * scale;
169 OSG::Real32 top = upperRight.y() * scale;
170 OSG::Real32 bottom = lowerLeft.y() * scale;
171 OSG::UInt32 posOffset = posPtr->size();
172 posPtr->push_back(OSG::Vec3f(left, bottom, 0.f));
173 posPtr->push_back(OSG::Vec3f(right, bottom, 0.f));
174 posPtr->push_back(OSG::Vec3f(right, top, 0.f));
175 posPtr->push_back(OSG::Vec3f(left, top, 0.f));
176 posIndicesPtr->push_back(posOffset);
177 colIndicesPtr->push_back(1);
178 posIndicesPtr->push_back(posOffset + 1);
179 colIndicesPtr->push_back(1);
180 posIndicesPtr->push_back(posOffset + 2);
181 colIndicesPtr->push_back(1);
182 posIndicesPtr->push_back(posOffset + 3);
183 colIndicesPtr->push_back(1);
185 // Text bounds & Line bounds
186 OSG::Vec2f pos, textPos, offset;
187 if (layoutParam.horizontal == true)
189 OSG::Real32 lineHeight = face->getHoriAscent() - face->getHoriDescent();
190 OSG::Real32 spacing = layoutParam.spacing * lineHeight;
191 if (layoutParam.topToBottom == true)
193 switch (layoutParam.minorAlignment)
195 case OSG::TextLayoutParam::ALIGN_BEGIN:
196 break;
197 case OSG::TextLayoutParam::ALIGN_FIRST:
198 pos[1] = textPos[1] = face->getHoriAscent();
199 break;
200 case OSG::TextLayoutParam::ALIGN_MIDDLE:
201 pos[1] = textPos[1] = (spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f;
202 break;
203 case OSG::TextLayoutParam::ALIGN_END:
204 pos[1] = textPos[1] = spacing * (layoutResult.lineBounds.size() - 1) + lineHeight;
205 break;
207 offset.setValues(0.f, -spacing);
209 else
211 switch (layoutParam.minorAlignment)
213 case OSG::TextLayoutParam::ALIGN_BEGIN:
214 pos[1] = lineHeight;
215 textPos[1] = spacing * (layoutResult.lineBounds.size() - 1) + lineHeight;
216 break;
217 case OSG::TextLayoutParam::ALIGN_FIRST:
218 pos[1] = face->getHoriAscent();
219 textPos[1] = spacing * (layoutResult.lineBounds.size() - 1) + face->getHoriAscent();
220 break;
221 case OSG::TextLayoutParam::ALIGN_MIDDLE:
222 pos[1] = -(spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f + lineHeight;
223 textPos[1] = (spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f;
224 break;
225 case OSG::TextLayoutParam::ALIGN_END:
226 pos[1] = -spacing * (layoutResult.lineBounds.size() - 1);
227 break;
229 offset.setValues(0.f, spacing);
232 else
234 OSG::Real32 lineHeight = face->getVertDescent() - face->getVertAscent();
235 OSG::Real32 spacing = layoutParam.spacing * lineHeight;
236 if (layoutParam.leftToRight == true)
238 switch (layoutParam.minorAlignment)
240 case OSG::TextLayoutParam::ALIGN_BEGIN:
241 break;
242 case OSG::TextLayoutParam::ALIGN_FIRST:
243 pos[0] = textPos[0] = face->getVertAscent();
244 break;
245 case OSG::TextLayoutParam::ALIGN_MIDDLE:
246 pos[0] = textPos[0] = -(spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f;
247 break;
248 case OSG::TextLayoutParam::ALIGN_END:
249 pos[0] = textPos[0] = -spacing * (layoutResult.lineBounds.size() - 1) - lineHeight;
250 break;
252 offset.setValues(spacing, 0.f);
254 else
256 switch (layoutParam.minorAlignment)
258 case OSG::TextLayoutParam::ALIGN_BEGIN:
259 pos[0] = -lineHeight;
260 textPos[0] = -spacing * (layoutResult.lineBounds.size() - 1) - lineHeight;
261 break;
262 case OSG::TextLayoutParam::ALIGN_FIRST:
263 pos[0] = -face->getVertDescent();
264 textPos[0] = -spacing * (layoutResult.lineBounds.size() - 1) -face->getVertDescent();
265 break;
266 case OSG::TextLayoutParam::ALIGN_MIDDLE:
267 pos[0] = (spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f - lineHeight;
268 textPos[0] = -(spacing * (layoutResult.lineBounds.size() - 1) + lineHeight) / 2.f;
269 break;
270 case OSG::TextLayoutParam::ALIGN_END:
271 pos[0] = spacing * (layoutResult.lineBounds.size() - 1);
272 break;
274 offset.setValues(-spacing, 0.f);
278 typesPtr->push_back(GL_LINE_LOOP);
279 lensPtr->push_back(4);
280 left = textPos.x();
281 top = textPos.y();
282 if (layoutParam.horizontal == true)
283 if (layoutParam.leftToRight == true)
284 switch (layoutParam.majorAlignment)
286 case OSG::TextLayoutParam::ALIGN_BEGIN:
287 case OSG::TextLayoutParam::ALIGN_FIRST:
288 break;
289 case OSG::TextLayoutParam::ALIGN_MIDDLE:
290 left -= layoutResult.textBounds.x() / 2.f;
291 break;
292 case OSG::TextLayoutParam::ALIGN_END:
293 left -= layoutResult.textBounds.x();
294 break;
296 else
297 switch (layoutParam.majorAlignment)
299 case OSG::TextLayoutParam::ALIGN_BEGIN:
300 case OSG::TextLayoutParam::ALIGN_FIRST:
301 left -= layoutResult.textBounds.x();
302 break;
303 case OSG::TextLayoutParam::ALIGN_MIDDLE:
304 left -= layoutResult.textBounds.x() / 2.f;
305 break;
306 case OSG::TextLayoutParam::ALIGN_END:
307 break;
309 else
310 if (layoutParam.topToBottom == true)
311 switch (layoutParam.majorAlignment)
313 case OSG::TextLayoutParam::ALIGN_BEGIN:
314 case OSG::TextLayoutParam::ALIGN_FIRST:
315 break;
316 case OSG::TextLayoutParam::ALIGN_MIDDLE:
317 top += layoutResult.textBounds.y() / 2.f;
318 break;
319 case OSG::TextLayoutParam::ALIGN_END:
320 top += layoutResult.textBounds.y();
321 break;
323 else
324 switch (layoutParam.majorAlignment)
326 case OSG::TextLayoutParam::ALIGN_BEGIN:
327 case OSG::TextLayoutParam::ALIGN_FIRST:
328 top += layoutResult.textBounds.y();
329 break;
330 case OSG::TextLayoutParam::ALIGN_MIDDLE:
331 top += layoutResult.textBounds.y() / 2.f;
332 break;
333 case OSG::TextLayoutParam::ALIGN_END:
334 break;
336 left *= scale;
337 right = left + layoutResult.textBounds.x() * scale;
338 top *= scale;
339 bottom = top - layoutResult.textBounds.y() * scale;
340 posOffset = posPtr->size();
341 posPtr->push_back(OSG::Vec3f(left, bottom, 0.f));
342 posPtr->push_back(OSG::Vec3f(right, bottom, 0.f));
343 posPtr->push_back(OSG::Vec3f(right, top, 0.f));
344 posPtr->push_back(OSG::Vec3f(left, top, 0.f));
345 posIndicesPtr->push_back(posOffset);
346 colIndicesPtr->push_back(3);
347 posIndicesPtr->push_back(posOffset + 1);
348 colIndicesPtr->push_back(3);
349 posIndicesPtr->push_back(posOffset + 2);
350 colIndicesPtr->push_back(3);
351 posIndicesPtr->push_back(posOffset + 3);
352 colIndicesPtr->push_back(3);
354 vector<OSG::Vec2f>::const_iterator lbIt;
355 for (lbIt = layoutResult.lineBounds.begin(); lbIt != layoutResult.lineBounds.end(); ++lbIt)
357 typesPtr->push_back(GL_LINE_LOOP);
358 lensPtr->push_back(4);
359 OSG::Real32 left = pos.x();
360 OSG::Real32 top = pos.y();
361 if (layoutParam.horizontal == true)
362 if (layoutParam.leftToRight == true)
363 switch (layoutParam.majorAlignment)
365 case OSG::TextLayoutParam::ALIGN_BEGIN:
366 case OSG::TextLayoutParam::ALIGN_FIRST:
367 break;
368 case OSG::TextLayoutParam::ALIGN_MIDDLE:
369 left -= lbIt->x() / 2.f;
370 break;
371 case OSG::TextLayoutParam::ALIGN_END:
372 left -= lbIt->x();
373 break;
375 else
376 switch (layoutParam.majorAlignment)
378 case OSG::TextLayoutParam::ALIGN_BEGIN:
379 case OSG::TextLayoutParam::ALIGN_FIRST:
380 left -= lbIt->x();
381 break;
382 case OSG::TextLayoutParam::ALIGN_MIDDLE:
383 left -= lbIt->x() / 2.f;
384 break;
385 case OSG::TextLayoutParam::ALIGN_END:
386 break;
388 else
389 if (layoutParam.topToBottom == true)
390 switch (layoutParam.majorAlignment)
392 case OSG::TextLayoutParam::ALIGN_BEGIN:
393 case OSG::TextLayoutParam::ALIGN_FIRST:
394 break;
395 case OSG::TextLayoutParam::ALIGN_MIDDLE:
396 top += lbIt->y() / 2.f;
397 break;
398 case OSG::TextLayoutParam::ALIGN_END:
399 top += lbIt->y();
400 break;
402 else
403 switch (layoutParam.majorAlignment)
405 case OSG::TextLayoutParam::ALIGN_BEGIN:
406 case OSG::TextLayoutParam::ALIGN_FIRST:
407 top += lbIt->y();
408 break;
409 case OSG::TextLayoutParam::ALIGN_MIDDLE:
410 top += lbIt->y() / 2.f;
411 break;
412 case OSG::TextLayoutParam::ALIGN_END:
413 break;
415 left *= scale;
416 OSG::Real32 right = left + lbIt->x() * scale;
417 top *= scale;
418 OSG::Real32 bottom = top - lbIt->y() * scale;
419 OSG::UInt32 posOffset = posPtr->size();
420 posPtr->push_back(OSG::Vec3f(left, bottom, 0.f));
421 posPtr->push_back(OSG::Vec3f(right, bottom, 0.f));
422 posPtr->push_back(OSG::Vec3f(right, top, 0.f));
423 posPtr->push_back(OSG::Vec3f(left, top, 0.f));
424 posIndicesPtr->push_back(posOffset);
425 colIndicesPtr->push_back(2);
426 posIndicesPtr->push_back(posOffset + 1);
427 colIndicesPtr->push_back(2);
428 posIndicesPtr->push_back(posOffset + 2);
429 colIndicesPtr->push_back(2);
430 posIndicesPtr->push_back(posOffset + 3);
431 colIndicesPtr->push_back(2);
433 typesPtr->push_back(GL_LINE_STRIP);
434 lensPtr->push_back(2);
435 posOffset = posPtr->size();
436 if (layoutParam.horizontal == true)
438 OSG::Real32 base = top - face->getHoriAscent() * scale;
439 posPtr->push_back(OSG::Vec3f(left, base, 0.f));
440 posPtr->push_back(OSG::Vec3f(right, base, 0.f));
442 else
444 OSG::Real32 base = left - face->getVertAscent() * scale;
445 posPtr->push_back(OSG::Vec3f(base, top, 0.f));
446 posPtr->push_back(OSG::Vec3f(base, bottom, 0.f));
448 posIndicesPtr->push_back(posOffset);
449 colIndicesPtr->push_back(2);
450 posIndicesPtr->push_back(posOffset + 1);
451 colIndicesPtr->push_back(2);
452 pos += offset;
455 OSG::SimpleMaterialUnrecPtr matPtr = OSG::SimpleMaterial::create();
456 geoPtr->setMaterial(matPtr);
458 OSG::NodeTransitPtr nodePtr = OSG::Node::create();
459 nodePtr->setCore(geoPtr);
461 return nodePtr;
464 void updateFace(void)
466 // Try to create new face
467 OSG::TextPixmapFaceRefPtr newFace = OSG::TextPixmapFace::create(family, style, 78);
468 if (newFace == 0)
469 return;
470 face = newFace;
472 // Update information on the screen
473 family = face->getFamily();
475 if(statfg->getCollector() != NULL)
477 statfg->getCollector()->getElem(familyDesc)->set(family);
478 style = face->getStyle();
479 OSG::StatStringElem *statElem = statfg->getCollector()->getElem(styleDesc);
480 switch (style)
482 case OSG::TextFace::STYLE_PLAIN:
483 statElem->set("Plain");
484 break;
485 case OSG::TextFace::STYLE_BOLD:
486 statElem->set("Bold");
487 break;
488 case OSG::TextFace::STYLE_ITALIC:
489 statElem->set("Italic");
490 break;
491 case OSG::TextFace::STYLE_BOLDITALIC:
492 statElem->set("Bold & Italic");
493 break;
498 const char *alignmentToString(OSG::TextLayoutParam::Alignment alignment)
500 switch (alignment)
502 case OSG::TextLayoutParam::ALIGN_FIRST:
503 return "First";
504 case OSG::TextLayoutParam::ALIGN_BEGIN:
505 return "Begin";
506 case OSG::TextLayoutParam::ALIGN_MIDDLE:
507 return "Middle";
508 case OSG::TextLayoutParam::ALIGN_END:
509 return "End";
510 default:
511 return "???";
515 void updateScene(void)
517 if(statfg->getCollector() != NULL)
519 statfg->getCollector()->getElem(majorAlignDesc)->set(alignmentToString(layoutParam.majorAlignment));
520 statfg->getCollector()->getElem(minorAlignDesc)->set(alignmentToString(layoutParam.minorAlignment));
521 statfg->getCollector()->getElem(dirDesc)->set(layoutParam.horizontal ? "Horizontal" : "Vertical");
522 statfg->getCollector()->getElem(horiDirDesc)->set(layoutParam.leftToRight ? "Left to right" : "Right to left");
523 statfg->getCollector()->getElem(vertDirDesc)->set(layoutParam.topToBottom ? "Top to bottom" : "Bottom to top");
526 if(face == NULL)
527 return;
529 OSG::TextLayoutResult layoutResult;
530 face->layout(lines, layoutParam, layoutResult);
531 OSG::Vec2f offset;
532 OSG::ImageUnrecPtr imagePtr = face->makeImage(layoutResult, offset);
533 OSG::Real32 width = imagePtr->getWidth();
534 OSG::Real32 height = imagePtr->getHeight();
535 OSG::Real32 scale = 2.f / (face->getHoriAscent() - face->getHoriDescent());
537 // Put it all together into a Geometry NodeCore.
538 OSG::GeometryUnrecPtr geo = OSG::makePlaneGeo(width * scale, height * scale, 1, 1);
539 OSG::NodeUnrecPtr textNode = OSG::Node::create();
540 textNode->setCore(geo);
541 OSG::NodeUnrecPtr transNodePtr = OSG::Node::create();
542 OSG::TransformUnrecPtr transPtr = OSG::Transform::create();
543 OSG::Matrix transMatrix;
544 transMatrix.setTranslate((offset.x() + width / 2.f) * scale, (offset.y() - height / 2.f) * scale, -0.03f);
545 transPtr->setMatrix(transMatrix);
546 transNodePtr->setCore(transPtr);
547 transNodePtr->addChild(textNode);
549 OSG::TextureObjChunkUnrecPtr texObjChunk = OSG::TextureObjChunk::create();
550 texObjChunk->setImage(imagePtr);
551 texObjChunk->setScale(false);
552 texObjChunk->setWrapS(GL_CLAMP);
553 texObjChunk->setWrapT(GL_CLAMP);
554 texObjChunk->setMagFilter(GL_NEAREST);
555 texObjChunk->setMinFilter(GL_NEAREST);
557 OSG::TextureEnvChunkUnrecPtr texEnvChunk = OSG::TextureEnvChunk::create();
558 texEnvChunk->setEnvMode(GL_MODULATE);
560 OSG::TextureTransformChunkUnrecPtr texTransChunk = OSG::TextureTransformChunk::create();
561 OSG::Real32 textureWidth = OSG::osgNextPower2(static_cast<OSG::UInt32>(width));
562 OSG::Real32 textureHeight = OSG::osgNextPower2(static_cast<OSG::UInt32>(height));
563 OSG::Matrix matrix;
564 matrix.setScale(width / textureWidth, height / textureHeight, 1.f);
565 texTransChunk->setMatrix(matrix);
567 OSG::MaterialChunkUnrecPtr matChunk = OSG::MaterialChunk::create();
568 matChunk->setAmbient(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
569 matChunk->setDiffuse(OSG::Color4f(1.f, 1.f, 1.f, 1.f));
570 matChunk->setEmission(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
571 matChunk->setSpecular(OSG::Color4f(0.f, 0.f, 0.f, 1.f));
572 matChunk->setShininess(0);
574 OSG::BlendChunkUnrecPtr blendChunk = OSG::BlendChunk::create();
575 blendChunk->setSrcFactor(GL_SRC_ALPHA);
576 blendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);
578 OSG::ChunkMaterialUnrecPtr m = OSG::ChunkMaterial::create();
579 m->addChunk(texObjChunk);
580 m->addChunk(texEnvChunk);
581 m->addChunk(texTransChunk);
582 m->addChunk(matChunk);
583 m->addChunk(blendChunk);
585 geo->setMaterial(m);
587 scene->clearChildren();
588 scene->addChild(createCoordinateCross());
589 scene->addChild(createMetrics(face, scale, layoutParam, layoutResult));
590 scene->addChild(transNodePtr);
593 // Initialize GLUT & OpenSG and set up the scene
594 int main(int argc, char **argv)
596 // OSG init
597 OSG::osgInit(argc,argv);
599 // GLUT init
600 int winid = setupGLUT(&argc, argv);
603 // the connection between GLUT and OpenSG
604 OSG::GLUTWindowUnrecPtr gwin= OSG::GLUTWindow::create();
605 gwin->setGlutId(winid);
606 gwin->init();
608 lines.push_back(argc >= 2 ? argv[1] : "Hello World!");
609 lines.push_back("Powered by OpenSG");
610 lines.push_back("3rd line");
611 layoutParam.spacing = 1.5f;
612 //layoutParam.length.push_back(10.f * 78.f);
613 //layoutParam.length.push_back(7.f * 78.f);
614 //layoutParam.length.push_back(-1.f * 78.f);
616 // put the geometry core into a node
617 scene = OSG::Node::create();
618 OSG::GroupUnrecPtr groupPtr = OSG::Group::create();
619 scene->setCore(groupPtr);
621 statfg = OSG::SimpleStatisticsForeground::create();
622 statfg->setSize(25);
623 statfg->setColor(OSG::Color4f(0,1,0,0.9f));
624 statfg->addElement(familyDesc, "Family: %s");
625 statfg->addElement(styleDesc, "Style: %s");
626 statfg->addElement(majorAlignDesc, "Major Alignment: %s");
627 statfg->addElement(minorAlignDesc, "Minor Alignment: %s");
628 statfg->addElement(dirDesc, "%s");
629 statfg->addElement(horiDirDesc, "%s");
630 statfg->addElement(vertDirDesc, "%s");
632 // Create the background
633 OSG::SolidBackgroundUnrecPtr bg = OSG::SolidBackground::create();
634 bg->setColor(OSG::Color3f(0.1f, 0.1f, 0.5f));
636 updateFace();
637 updateScene();
639 // create the SimpleSceneManager helper
640 mgr = OSG::SimpleSceneManager::create();
642 // tell the manager what to manage
643 mgr->setWindow(gwin );
644 mgr->setRoot (scene);
646 // show the whole scene
647 mgr->showAll();
649 // add the statistics forground and the background
650 gwin->getPort(0)->addForeground(statfg);
651 gwin->getPort(0)->setBackground(bg);
654 // GLUT main loop
655 glutMainLoop();
657 return 0;
661 // GLUT callback functions
664 // redraw the window
665 void display( void )
667 mgr->redraw();
670 // react to size changes
671 void reshape(int w, int h)
673 mgr->resize(w, h);
674 glutPostRedisplay();
677 // react to mouse button presses
678 void mouse(int button, int state, int x, int y)
680 if (state)
681 mgr->mouseButtonRelease(button, x, y);
682 else
683 mgr->mouseButtonPress(button, x, y);
685 glutPostRedisplay();
688 // react to mouse motions with pressed buttons
689 void motion(int x, int y)
691 mgr->mouseMove(x, y);
692 glutPostRedisplay();
695 // react to keys
696 void keyboard(unsigned char k, int x, int y)
698 switch(k)
700 case 27:
702 mgr = NULL;
703 face = NULL;
704 scene = NULL;
705 statfg = NULL;
707 OSG::osgExit();
708 exit(0);
710 break;
714 #define COMMAND_FAMILY_SANS 701
715 #define COMMAND_FAMILY_SERIF 702
716 #define COMMAND_FAMILY_TYPEWRITER 703
717 #define COMMAND_FAMILY_BASE 704
718 #define COMMAND_STYLE_PLAIN 301
719 #define COMMAND_STYLE_BOLD 302
720 #define COMMAND_STYLE_ITALIC 303
721 #define COMMAND_STYLE_BOLDITALIC 304
722 #define COMMAND_MAJORALIGNMENT_FIRST 101
723 #define COMMAND_MAJORALIGNMENT_BEGIN 102
724 #define COMMAND_MAJORALIGNMENT_MIDDLE 103
725 #define COMMAND_MAJORALIGNMENT_END 104
726 #define COMMAND_MINORALIGNMENT_FIRST 201
727 #define COMMAND_MINORALIGNMENT_BEGIN 202
728 #define COMMAND_MINORALIGNMENT_MIDDLE 203
729 #define COMMAND_MINORALIGNMENT_END 204
730 #define COMMAND_HORIZONTAL 401
731 #define COMMAND_VERTICAL 402
732 #define COMMAND_LEFTTORIGHT 501
733 #define COMMAND_RIGHTTOLEFT 502
734 #define COMMAND_TOPTOBOTTOM 601
735 #define COMMAND_BOTTOMTOTOP 602
737 void menu(int command)
739 switch (command)
741 case COMMAND_FAMILY_SANS:
742 family = "SANS";
743 updateFace();
744 break;
745 case COMMAND_FAMILY_SERIF:
746 family = "SERIF";
747 updateFace();
748 break;
749 case COMMAND_FAMILY_TYPEWRITER:
750 family = "TYPEWRITER";
751 updateFace();
752 break;
753 case COMMAND_STYLE_PLAIN:
754 style = OSG::TextFace::STYLE_PLAIN;
755 updateFace();
756 break;
757 case COMMAND_STYLE_BOLD:
758 style = OSG::TextFace::STYLE_BOLD;
759 updateFace();
760 break;
761 case COMMAND_STYLE_ITALIC:
762 style = OSG::TextFace::STYLE_ITALIC;
763 updateFace();
764 break;
765 case COMMAND_STYLE_BOLDITALIC:
766 style = OSG::TextFace::STYLE_BOLDITALIC;
767 updateFace();
768 break;
769 case COMMAND_MAJORALIGNMENT_FIRST:
770 layoutParam.majorAlignment = OSG::TextLayoutParam::ALIGN_FIRST;
771 break;
772 case COMMAND_MAJORALIGNMENT_BEGIN:
773 layoutParam.majorAlignment = OSG::TextLayoutParam::ALIGN_BEGIN;
774 break;
775 case COMMAND_MAJORALIGNMENT_MIDDLE:
776 layoutParam.majorAlignment = OSG::TextLayoutParam::ALIGN_MIDDLE;
777 break;
778 case COMMAND_MAJORALIGNMENT_END:
779 layoutParam.majorAlignment = OSG::TextLayoutParam::ALIGN_END;
780 break;
781 case COMMAND_MINORALIGNMENT_FIRST:
782 layoutParam.minorAlignment = OSG::TextLayoutParam::ALIGN_FIRST;
783 break;
784 case COMMAND_MINORALIGNMENT_BEGIN:
785 layoutParam.minorAlignment = OSG::TextLayoutParam::ALIGN_BEGIN;
786 break;
787 case COMMAND_MINORALIGNMENT_MIDDLE:
788 layoutParam.minorAlignment = OSG::TextLayoutParam::ALIGN_MIDDLE;
789 break;
790 case COMMAND_MINORALIGNMENT_END:
791 layoutParam.minorAlignment = OSG::TextLayoutParam::ALIGN_END;
792 break;
793 case COMMAND_HORIZONTAL:
794 layoutParam.horizontal = true;
795 glutSetMenu(mainMenuID);
796 glutChangeToMenuEntry(5, "Vertical", COMMAND_VERTICAL);
797 break;
798 case COMMAND_VERTICAL:
799 layoutParam.horizontal = false;
800 glutSetMenu(mainMenuID);
801 glutChangeToMenuEntry(5, "Horizontal", COMMAND_HORIZONTAL);
802 break;
803 case COMMAND_LEFTTORIGHT:
804 layoutParam.leftToRight = true;
805 glutSetMenu(mainMenuID);
806 glutChangeToMenuEntry(6, "Right to left", COMMAND_RIGHTTOLEFT);
807 break;
808 case COMMAND_RIGHTTOLEFT:
809 layoutParam.leftToRight = false;
810 glutSetMenu(mainMenuID);
811 glutChangeToMenuEntry(6, "Left to right", COMMAND_LEFTTORIGHT);
812 break;
813 case COMMAND_TOPTOBOTTOM:
814 layoutParam.topToBottom = true;
815 glutSetMenu(mainMenuID);
816 glutChangeToMenuEntry(7, "Bottom to top", COMMAND_BOTTOMTOTOP);
817 break;
818 case COMMAND_BOTTOMTOTOP:
819 layoutParam.topToBottom = false;
820 glutSetMenu(mainMenuID);
821 glutChangeToMenuEntry(7, "Top to bottom", COMMAND_TOPTOBOTTOM);
822 break;
823 default:
824 if (command < COMMAND_FAMILY_BASE)
825 return;
826 family = families[command - COMMAND_FAMILY_BASE];
827 updateFace();
829 updateScene();
830 mgr->showAll();
831 glutPostRedisplay();
834 // setup the GLUT library which handles the windows for us
835 int setupGLUT(int *argc, char *argv[])
837 glutInit(argc, argv);
838 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
840 int winid = glutCreateWindow("OpenSG");
842 glutReshapeFunc(reshape);
843 glutDisplayFunc(display);
844 glutMouseFunc(mouse);
845 glutMotionFunc(motion);
846 glutKeyboardFunc(keyboard);
848 int familyMenuID = glutCreateMenu(menu);
849 glutSetMenu(familyMenuID);
850 glutAddMenuEntry("SANS", COMMAND_FAMILY_SANS);
851 glutAddMenuEntry("SERIF", COMMAND_FAMILY_SERIF);
852 glutAddMenuEntry("TYPEWRITER", COMMAND_FAMILY_TYPEWRITER);
853 OSG::TextFaceFactory::the()->getFontFamilies(families);
854 OSG::UInt32 i;
855 for (i = 0; i < families.size(); ++i)
856 glutAddMenuEntry(families[i].c_str(), COMMAND_FAMILY_BASE + i);
857 int styleMenuID = glutCreateMenu(menu);
858 glutSetMenu(styleMenuID);
859 glutAddMenuEntry("Plain", COMMAND_STYLE_PLAIN);
860 glutAddMenuEntry("Bold", COMMAND_STYLE_BOLD);
861 glutAddMenuEntry("Italic", COMMAND_STYLE_ITALIC);
862 glutAddMenuEntry("Bold + Italic", COMMAND_STYLE_BOLDITALIC);
863 int majorAlignmentMenuID = glutCreateMenu(menu);
864 glutSetMenu(majorAlignmentMenuID);
865 glutAddMenuEntry("First", COMMAND_MAJORALIGNMENT_FIRST);
866 glutAddMenuEntry("Begin", COMMAND_MAJORALIGNMENT_BEGIN);
867 glutAddMenuEntry("Middle", COMMAND_MAJORALIGNMENT_MIDDLE);
868 glutAddMenuEntry("End", COMMAND_MAJORALIGNMENT_END);
869 int minorAlignmentMenuID = glutCreateMenu(menu);
870 glutSetMenu(minorAlignmentMenuID);
871 glutAddMenuEntry("First", COMMAND_MINORALIGNMENT_FIRST);
872 glutAddMenuEntry("Begin", COMMAND_MINORALIGNMENT_BEGIN);
873 glutAddMenuEntry("Middle", COMMAND_MINORALIGNMENT_MIDDLE);
874 glutAddMenuEntry("End", COMMAND_MINORALIGNMENT_END);
875 mainMenuID = glutCreateMenu(menu);
876 glutSetMenu(mainMenuID);
877 glutAddSubMenu("Family", familyMenuID);
878 glutAddSubMenu("Style", styleMenuID);
879 glutAddSubMenu("Major Alignment", majorAlignmentMenuID);
880 glutAddSubMenu("Minor Alignment", minorAlignmentMenuID);
881 glutAddMenuEntry("Vertical", COMMAND_VERTICAL);
882 glutAddMenuEntry("Right to left", COMMAND_RIGHTTOLEFT);
883 glutAddMenuEntry("Bottom to top", COMMAND_BOTTOMTOTOP);
884 glutAttachMenu(GLUT_RIGHT_BUTTON);
886 return winid;