Changeset 9881 for OpenSceneGraph/trunk/src/osgText/Text3D.cpp
- Timestamp:
- 03/10/09 11:56:00 (4 years ago)
- Files:
-
- 1 modified
-
OpenSceneGraph/trunk/src/osgText/Text3D.cpp (modified) (47 diffs)
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgText/Text3D.cpp
r8868 r9881 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 5 * (at your option) any later version. The full license is in LICENSE file 6 6 * included with this distribution, and on the openscenegraph.org website. 7 * 7 * 8 8 * This library is distributed in the hope that it will be useful, 9 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 11 * OpenSceneGraph Public License for more details. 12 12 */ … … 14 14 #include <osgText/Text3D> 15 15 #include <osg/io_utils> 16 namespace osgText 16 namespace osgText 17 17 { 18 18 … … 33 33 } 34 34 35 //void Text3D::accept(osg::Drawable::ConstAttributeFunctor& af) const 36 //{ 37 // TODO 38 //} 39 40 //void Text3D::accept(osg::PrimitiveFunctor& /*pf*/) const 41 //{ 42 // TODO 43 //} 35 void Text3D::accept(osg::Drawable::ConstAttributeFunctor& af) const 36 { 37 // ** for each line, do ... 38 TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end(); 39 for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine) 40 { 41 // ** for each glyph in the line, do ... 42 LineRenderInfo::const_iterator it, end = itLine->end(); 43 for (it = itLine->begin(); it!=end; ++it) 44 { 45 // ** apply the vertex array 46 af.apply(osg::Drawable::VERTICES, it->_glyph->getVertexArray()->size(), &(it->_glyph->getVertexArray()->front())); 47 } 48 } 49 } 50 void Text3D::accept(osg::PrimitiveFunctor& pf) const 51 { 52 // ** for each line, do ... 53 TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end(); 54 for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine) 55 { 56 // ** for each glyph in the line, do ... 57 LineRenderInfo::const_iterator it, end = itLine->end(); 58 for (it = itLine->begin(); it!=end; ++it) 59 { 60 pf.setVertexArray(it->_glyph->getVertexArray()->size(),&(it->_glyph->getVertexArray()->front())); 61 62 // ** render the front face of the glyph 63 osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList(); 64 for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslFront.begin(), end = pslFront.end(); itr!=end; ++itr) 65 { 66 (*itr)->accept(pf); 67 } 68 69 // ** render the wall face of the glyph 70 osg::Geometry::PrimitiveSetList & pslWall = it->_glyph->getWallPrimitiveSetList(); 71 for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslWall.begin(), end=pslWall.end(); itr!=end; ++itr) 72 { 73 (*itr)->accept(pf); 74 } 75 76 // ** render the back face of the glyph 77 osg::Geometry::PrimitiveSetList & pslBack = it->_glyph->getBackPrimitiveSetList(); 78 for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslBack.begin(), end=pslBack.end(); itr!=end; ++itr) 79 { 80 (*itr)->accept(pf); 81 } 82 } 83 } 84 } 44 85 45 86 void Text3D::setFont(osg::ref_ptr<Font3D> font) 46 { 87 { 47 88 _font = font; 48 89 49 90 computeGlyphRepresentation(); 50 91 } 51 92 52 93 void Text3D::setFont(const std::string & fontfile) 53 { 94 { 54 95 setFont(readRefFont3DFile(fontfile)); 55 96 } … … 76 117 float maximumHeight = _maximumHeight / _font->getScale(); 77 118 float maximumWidth = _maximumWidth / _font->getScale(); 78 119 79 120 for(bool outOfSpace=false;lastChar!=last;++lastChar) 80 121 { 81 122 unsigned int charcode = *lastChar; 82 123 83 124 if (charcode=='\n') 84 125 { … … 90 131 { 91 132 const osg::BoundingBox & bb = glyph->getBoundingBox(); 92 133 93 134 // adjust cursor position w.r.t any kerning. 94 135 if (previous_charcode) 95 136 { 96 137 97 138 if (_layout == RIGHT_TO_LEFT) 98 139 { 99 140 cursor.x() -= glyph->getHorizontalAdvance(); 100 141 } 101 142 102 143 if (kerning) 103 144 { … … 120 161 } 121 162 else 122 { 163 { 123 164 switch (_layout) 124 165 { … … 136 177 break; 137 178 } 138 139 } 140 141 179 180 } 181 182 142 183 143 184 switch(_layout) … … 159 200 break; 160 201 } 161 202 162 203 // => word boundary detection & wrapping 163 204 if (outOfSpace) break; … … 176 217 177 218 } 178 219 179 220 // word boundary detection & wrapping 180 221 if (lastChar!=last) 181 222 { 182 if (deliminatorSet.count(*lastChar)==0) 223 if (deliminatorSet.count(*lastChar)==0) 183 224 { 184 225 String::iterator lastValidChar = lastChar; … … 186 227 { 187 228 --lastValidChar; 188 229 189 230 //Substract off glyphs from the cursor position (to correctly center text) 190 231 Font3D::Glyph3D* glyph = _font->getGlyph(*lastValidChar); … … 199 240 } 200 241 } 201 242 202 243 if (first!=lastValidChar) 203 244 { … … 214 255 { 215 256 if (_font.valid() == false) return; 216 257 217 258 _textRenderInfo.clear(); 218 259 _lineCount = 0; 219 220 if (_text.empty()) 260 261 if (_text.empty()) 221 262 { 222 263 _textBB.set(0,0,0, 0,0,0);//no size text … … 224 265 return; 225 266 } 226 267 227 268 // initialize bounding box, it will be expanded during glyph position calculation 228 269 _textBB.init(); … … 232 273 osg::Vec2 local(0.0f,0.0f); 233 274 osg::Vec2 startOffset(0.0f,0.0f); 234 275 235 276 unsigned int previous_charcode = 0; 236 277 unsigned int linelength = 0; 237 278 bool kerning = true; 238 279 239 280 unsigned int lineNumber = 0; 240 281 241 282 242 283 243 284 for(String::iterator itr=_text.begin(); itr!=_text.end(); ) … … 245 286 _textRenderInfo.resize(lineNumber + 1); 246 287 LineRenderInfo & currentLineRenderInfo = _textRenderInfo.back(); 247 288 248 289 // record the start of the current line 249 290 String::iterator startOfLine_itr = itr; … … 252 293 osg::Vec2 endOfLine_coords(cursor); 253 294 String::iterator endOfLine_itr = computeLastCharacterOnLine(endOfLine_coords, itr,_text.end()); 254 255 // ** position the cursor function to the Layout and the alignement 295 296 // ** position the cursor function to the Layout and the alignement 256 297 TextBase::positionCursor(endOfLine_coords, cursor, (unsigned int) (endOfLine_itr - startOfLine_itr)); 257 298 258 299 259 300 if (itr!=endOfLine_itr) 260 301 { … … 267 308 { 268 309 const osg::BoundingBox & bb = glyph->getBoundingBox(); 269 310 270 311 // adjust cursor position w.r.t any kerning. 271 312 if (previous_charcode) … … 275 316 cursor.x() -= glyph->getHorizontalAdvance(); 276 317 } 277 318 278 319 if (kerning) 279 320 { … … 296 337 } 297 338 else 298 { 339 { 299 340 switch (_layout) 300 341 { … … 315 356 } 316 357 } 317 358 318 359 } 319 360 320 361 local = cursor; 321 362 322 363 if (_layout==VERTICAL) 323 364 { … … 325 366 local.y() += -glyph->getVerticalBearing().y(); 326 367 } 327 328 329 368 369 370 330 371 // move the cursor onto the next character. 331 372 // also expand bounding box … … 345 386 _textBB.expandBy(osg::Vec3(cursor.x()+bb.xMax(), cursor.y() + bb.yMax(), 0.0f)); //upper right corner 346 387 _textBB.expandBy(osg::Vec3(cursor.x()+bb.xMin(), cursor.y()+bb.yMin(), 0.0f)); //lower left corner 347 388 348 389 break; 349 390 } 350 391 351 392 osg::Vec3 pos = osg::Vec3(local.x(), local.y(), 0.0f); 352 393 currentLineRenderInfo.push_back(Text3D::GlyphRenderInfo(glyph, pos)); 353 394 354 395 355 396 previous_charcode = charcode; 356 397 } … … 361 402 ++itr; 362 403 } 363 404 364 405 if (itr!=_text.end()) 365 406 { … … 367 408 if (*itr=='\n') ++itr; 368 409 } 369 410 370 411 // move to new line. 371 412 switch(_layout) … … 395 436 } 396 437 _textBB.expandBy(0.0f,0.0f,-1); 397 438 398 439 TextBase::computePositions(); 399 440 } 400 401 402 441 403 442 osg::BoundingBox Text3D::computeBound() const … … 411 450 osg::Matrix& matrix = _autoTransformCache[i]._matrix; 412 451 bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix); 413 // bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*matrix);414 452 bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax())*matrix); 415 // bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix); 416 } 417 } 418 453 } 454 } 455 419 456 return bbox; 420 457 } 421 458 422 423 424 425 426 427 428 459 void Text3D::computePositions(unsigned int contextID) const 429 460 { 430 461 if (_font.valid() == false) return; 431 462 432 463 switch(_alignment) 433 464 { … … 447 478 case CENTER_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,0.0f,0.0f); break; 448 479 case RIGHT_BASE_LINE: _offset.set(_textBB.xMax(),0.0f,0.0f); break; 449 480 450 481 case LEFT_BOTTOM_BASE_LINE: _offset.set(0.0f,-_characterHeight*(_lineCount-1),0.0f); break; 451 482 case CENTER_BOTTOM_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,-_characterHeight*(_lineCount-1),0.0f); break; 452 483 case RIGHT_BOTTOM_BASE_LINE: _offset.set(_textBB.xMax(),-_characterHeight*(_lineCount-1),0.0f); break; 453 484 } 454 485 455 486 AutoTransformCache& atc = _autoTransformCache[contextID]; 456 487 osg::Matrix& matrix = atc._matrix; 457 488 458 489 459 490 float scale = _font->getScale(); 460 491 osg::Vec3 scaleVec(scale * _characterHeight, scale * _characterHeight / _characterAspectRatio, _characterDepth); … … 464 495 matrix.postMultTranslate(_position); 465 496 466 497 467 498 _normal = osg::Matrix::transform3x3(osg::Vec3(0.0f,0.0f,1.0f),matrix); 468 499 _normal.normalize(); 469 500 470 const_cast<Text3D*>(this)->dirtyBound(); 501 const_cast<Text3D*>(this)->dirtyBound(); 471 502 } 472 503 … … 475 506 osg::State & state = *renderInfo.getState(); 476 507 unsigned int contextID = state.getContextID(); 477 478 508 509 479 510 // ** save the previous modelview matrix 480 511 osg::ref_ptr<osg::RefMatrix> previous(new osg::RefMatrix(state.getModelViewMatrix())); … … 485 516 // ** mult previous by the modelview for this context 486 517 modelview->postMult(*previous.get()); 487 518 488 519 // ** apply this new modelview matrix 489 520 state.applyModelViewMatrix(modelview.get()); 490 491 521 522 492 523 if (_drawMode & TEXT) 493 524 { 494 525 renderInfo.getState()->disableAllVertexArrays(); 495 526 496 527 glPushAttrib(GL_TRANSFORM_BIT); 497 528 glEnable(GL_RESCALE_NORMAL); 498 529 499 530 switch(_renderMode) 500 531 { … … 503 534 default: renderPerGlyph(*renderInfo.getState()); break; 504 535 } 505 536 506 537 glPopAttrib(); 507 538 } … … 515 546 osg::Vec3 c110(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax())); 516 547 osg::Vec3 c010(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMax())); 517 548 518 549 osg::Vec3 c001(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())); 519 550 osg::Vec3 c101(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())); 520 551 osg::Vec3 c111(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())); 521 552 osg::Vec3 c011(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())); 522 553 523 554 glBegin(GL_LINE_LOOP); 524 555 glVertex3fv(c000.ptr()); … … 527 558 glVertex3fv(c010.ptr()); 528 559 glEnd(); 529 560 530 561 glBegin(GL_LINE_LOOP); 531 562 glVertex3fv(c001.ptr()); … … 534 565 glVertex3fv(c101.ptr()); 535 566 glEnd(); 536 567 537 568 glBegin(GL_LINES); 538 569 glVertex3fv(c000.ptr()); 539 570 glVertex3fv(c001.ptr()); 540 571 541 572 glVertex3fv(c100.ptr()); 542 573 glVertex3fv(c101.ptr()); 543 574 544 575 glVertex3fv(c110.ptr()); 545 576 glVertex3fv(c111.ptr()); 546 577 547 578 glVertex3fv(c010.ptr()); 548 579 glVertex3fv(c011.ptr()); 549 580 glEnd(); 550 581 } 551 } 582 } 552 583 553 584 if (_drawMode & ALIGNMENT) … … 566 597 glVertex3fv(vb.ptr()); 567 598 glEnd(); 568 599 569 600 } 570 601 … … 573 604 } 574 605 575 576 577 606 void Text3D::renderPerGlyph(osg::State & state) const 578 { 607 { 579 608 // ** for each line, do ... 580 609 TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end(); … … 585 614 for (it = itLine->begin(); it!=end; ++it) 586 615 { 587 616 588 617 glPushMatrix(); 589 618 590 619 glTranslatef(it->_position.x(), it->_position.y(), it->_position.z()); 591 620 592 621 // ** apply the vertex array 593 622 state.setVertexPointer(it->_glyph->getVertexArray()); 594 623 595 624 // ** render the front face of the glyph 596 625 glNormal3f(0.0f,0.0f,1.0f); 597 626 598 627 osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList(); 599 628 for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslFront.begin(), end = pslFront.end(); itr!=end; ++itr) 600 629 { 601 602 630 (*itr)->draw(state, false); 603 631 } 604 632 605 633 // ** render the wall face of the glyph 606 634 state.setNormalPointer(it->_glyph->getNormalArray()); … … 610 638 (*itr)->draw(state, false); 611 639 } 612 640 state.disableNormalPointer(); 641 613 642 // ** render the back face of the glyph 614 643 glNormal3f(0.0f,0.0f,-1.0f); 615 644 616 645 osg::Geometry::PrimitiveSetList & pslBack = it->_glyph->getBackPrimitiveSetList(); 617 646 for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslBack.begin(), end=pslBack.end(); itr!=end; ++itr) … … 619 648 (*itr)->draw(state, false); 620 649 } 621 650 622 651 glPopMatrix(); 623 652 } … … 629 658 // ** render all front faces 630 659 glNormal3f(0.0f,0.0f,1.0f); 631 660 632 661 TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end(); 633 662 for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine) … … 635 664 // ** for each glyph in the line, do ... 636 665 LineRenderInfo::const_iterator it, end = itLine->end(); 637 for (it = itLine->begin(); it!=end; ++it) 666 for (it = itLine->begin(); it!=end; ++it) 638 667 { 639 668 glPushMatrix(); 640 669 glTranslatef(it->_position.x(), it->_position.y(), it->_position.z()); 641 670 state.setVertexPointer(it->_glyph->getVertexArray()); 642 671 643 672 // ** render the front face of the glyph 644 673 osg::Geometry::PrimitiveSetList & psl = it->_glyph->getFrontPrimitiveSetList(); … … 650 679 } 651 680 } 652 681 653 682 654 683 // ** render all wall face of the text … … 663 692 state.setVertexPointer(it->_glyph->getVertexArray()); 664 693 state.setNormalPointer(it->_glyph->getNormalArray()); 665 694 666 695 osg::Geometry::PrimitiveSetList & psl = it->_glyph->getWallPrimitiveSetList(); 667 696 for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr) … … 673 702 } 674 703 675 704 676 705 // ** render all back face of the text 677 706 glNormal3f(0.0f,0.0f,-1.0f); 678 707 679 708 for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine) 680 709 { … … 686 715 glTranslatef(it->_position.x(), it->_position.y(), it->_position.z()); 687 716 state.setVertexPointer(it->_glyph->getVertexArray()); 688 717 689 718 // ** render the back face of the glyph 690 719 osg::Geometry::PrimitiveSetList & psl = it->_glyph->getBackPrimitiveSetList(); … … 710 739 { 711 740 TextBase::resizeGLObjectBuffers(maxSize); 712 741 713 742 if (_font.valid()) _font->resizeGLObjectBuffers(maxSize); 714 743 } … … 717 746 { 718 747 TextBase::releaseGLObjects(state); 719 748 720 749 if (_font.valid()) _font->releaseGLObjects(state); 721 750 }
