Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGTextVectorFace.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 #ifdef _MSC_VER
00040 # pragma warning (disable: 4786)
00041 #endif
00042 
00043 #include "OSGTextVectorFace.h"
00044 #include "OSGTextVectorGlyph.h"
00045 #include "OSGTextLayoutResult.h"
00046 #include "OSGTextFaceFactory.h"
00047 
00048 #ifdef __sgi
00049 # include <assert.h>
00050 #else
00051 # include <cassert>
00052 #endif
00053 
00054 
00055 using namespace std;
00056 
00057 
00058 OSG_BEGIN_NAMESPACE
00059 
00060 
00061 //----------------------------------------------------------------------
00062 // Static Class Variable implementations:
00063 // Author: pdaehne
00064 //----------------------------------------------------------------------
00065 TextVectorGlyph TextVectorFace::_emptyGlyph;
00066 
00067 
00068 //----------------------------------------------------------------------
00069 // Destructor
00070 // Author: pdaehne
00071 //----------------------------------------------------------------------
00072 TextVectorFace::~TextVectorFace()
00073 {
00074     // Delete all glyphs in the glyph cache
00075     GlyphMap::iterator it;
00076     for (it = _glyphMap.begin(); it != _glyphMap.end(); ++it)
00077     {
00078         assert(it->second != 0);
00079         delete it->second;
00080     }
00081 }
00082 
00083 
00084 //----------------------------------------------------------------------
00085 // Returns information about a glyph.
00086 // Author: pdaehne
00087 //----------------------------------------------------------------------
00088 const TextGlyph &TextVectorFace::getGlyph(TextGlyph::Index glyphIndex)
00089 {
00090     return getVectorGlyph(glyphIndex);
00091 }
00092 
00093 
00094 //----------------------------------------------------------------------
00095 // Returns information about a glyph.
00096 // Author: pdaehne
00097 //----------------------------------------------------------------------
00098 const TextVectorGlyph &TextVectorFace::getVectorGlyph(TextGlyph::Index glyphIndex)
00099 {
00100     if (glyphIndex == TextGlyph::INVALID_INDEX)
00101         return _emptyGlyph;
00102 
00103     // Try to find the glyph in the map of glyphs
00104     GlyphMap::const_iterator it = _glyphMap.find(glyphIndex);
00105     if (it != _glyphMap.end())
00106     {
00107         assert(it->second != 0);
00108         return *(it->second);
00109     }
00110 
00111     // We did not find the glyph, so we have to create it
00112     auto_ptr<TextVectorGlyph> glyph = createGlyph(glyphIndex);
00113 
00114     // We could not create the glyph, return 0
00115     if (glyph.get() == 0)
00116         return _emptyGlyph;
00117 
00118     // Put the glyph into the glyph cache
00119     _glyphMap.insert(GlyphMap::value_type(glyphIndex, glyph.get()));
00120 
00121     // Return the glyph
00122     return *(glyph.release());
00123 }
00124 
00125 
00126 //----------------------------------------------------------------------
00127 // Fills a geometry with a new text
00128 // Author: afischle, pdaehne
00129 //----------------------------------------------------------------------
00130 void TextVectorFace::fillGeo(GeometryPtr &geoPtr, const TextLayoutResult &layoutResult,
00131                              Real32 scale, Real32 depth, UInt32 level,
00132                              Real32 creaseAngle)
00133 {
00134     beginEditCP(geoPtr);
00135 
00136     // cast the field containers down to the needed type and create them
00137     // when they have the wrong type
00138     GeoPositions3fPtr posPtr = GeoPositions3fPtr::dcast(geoPtr->getPositions());
00139     if (posPtr == NullFC)
00140     {
00141         posPtr = GeoPositions3f::create();
00142         geoPtr->setPositions(posPtr);
00143     }
00144     else
00145         posPtr->clear();
00146     GeoNormals3fPtr normalsPtr = GeoNormals3fPtr::dcast(geoPtr->getNormals());
00147     if (normalsPtr == NullFC)
00148     {
00149         normalsPtr = GeoNormals3f::create();
00150         geoPtr->setNormals(normalsPtr);
00151     }
00152     else
00153         normalsPtr->clear();
00154     GeoTexCoords2fPtr texPtr = GeoTexCoords2fPtr::dcast(geoPtr->getTexCoords());
00155     if (texPtr == NullFC)
00156     {
00157         texPtr = GeoTexCoords2f::create();
00158         geoPtr->setTexCoords(texPtr);
00159     }
00160     else
00161         texPtr->clear();
00162     GeoPLengthsUI32Ptr lensPtr = GeoPLengthsUI32Ptr::dcast(geoPtr->getLengths());
00163     if (lensPtr == NullFC)
00164     {
00165         lensPtr = GeoPLengthsUI32::create();
00166         geoPtr->setLengths(lensPtr);
00167     }
00168     else
00169         lensPtr->clear();
00170     GeoIndicesUI32Ptr indicesPtr = GeoIndicesUI32Ptr::dcast(geoPtr->getIndices());
00171     if (indicesPtr == NullFC)
00172     {
00173         indicesPtr = GeoIndicesUI32::create();
00174         geoPtr->setIndices(indicesPtr);
00175     }
00176     else
00177         indicesPtr->clear();
00178     GeoPTypesUI8Ptr typesPtr = GeoPTypesUI8Ptr::dcast(geoPtr->getTypes());
00179     if (typesPtr == NullFC)
00180     {
00181         typesPtr = GeoPTypesUI8::create();
00182         geoPtr->setTypes(typesPtr);
00183     }
00184     else
00185         typesPtr->clear();
00186 
00187     geoPtr->setColors(NullFC);
00188     geoPtr->setSecondaryColors(NullFC);
00189     geoPtr->setTexCoords1(NullFC);
00190     geoPtr->setTexCoords2(NullFC);
00191     geoPtr->setTexCoords3(NullFC);
00192     geoPtr->getIndexMapping().clear();
00193 
00194     UInt32 numGlyphs = layoutResult.getNumGlyphs();
00195     if (numGlyphs == 0)
00196     {
00197         endEditCP(geoPtr);
00198         return;
00199     }
00200 
00201     // the interleaved multi-index blocks have the layout
00202     // Position | Normal | TexCoord
00203     geoPtr->getIndexMapping().push_back(Geometry::MapPosition);
00204     geoPtr->getIndexMapping().push_back(Geometry::MapNormal);
00205     geoPtr->getIndexMapping().push_back(Geometry::MapTexCoords);
00206 
00207     beginEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
00208     beginEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
00209     beginEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
00210     beginEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
00211     beginEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
00212     beginEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
00213 
00214     // store the normal for the front face
00215     normalsPtr->push_back(Vec3f(0.f, 0.f, 1.f));
00216     if (depth > 0.f)
00217         // store the normal for the back face
00218         normalsPtr->push_back(Vec3f(0.f, 0.f, -1.f));
00219 
00220     UInt32 i;
00221     for (i = 0; i < numGlyphs; ++i)
00222     {
00223         const TextVectorGlyph &glyph = getVectorGlyph(layoutResult.indices[i]);
00224         const TextVectorGlyph::PolygonOutline &outline = glyph.getLines(level);
00225         const Vec2f &pos = layoutResult.positions[i];
00226 
00227         // add the front face to the geometry
00228 
00229         // store positions and texture coordinates
00230         UInt32 coordOffset = posPtr->size();
00231         UInt32 texCoordOffset = texPtr->size();
00232         Real32 coordZ = 0.5f * depth;
00233         vector<Vec2f>::const_iterator cIt;
00234         for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt)
00235         {
00236             Vec2f coord = *cIt + pos;
00237             Vec2f texCoord = coord;
00238             coord *= scale;
00239             posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ));
00240             texCoord -= layoutResult.positions.front();
00241             texPtr->push_back(texCoord);
00242         }
00243 
00244         // Store types, lengths and indices
00245         vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt;
00246         UInt32 indexBegin = 0, indexEnd;
00247         for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt)
00248         {
00249             typesPtr->push_back(tIt->first);
00250             indexEnd = tIt->second;
00251             assert(indexEnd >= indexBegin);
00252             lensPtr->push_back(indexEnd - indexBegin);
00253             UInt32 i;
00254             for (i = indexBegin; i < indexEnd; ++i)
00255             {
00256                 // the interleaved multi-index blocks have the layout
00257                 // Position | Normal | TexCoord
00258                 assert(i < outline.indices.size());
00259                 UInt32 index = outline.indices[i];
00260                 assert(coordOffset + index < posPtr->size());
00261                 indicesPtr->push_back(coordOffset + index);
00262                 indicesPtr->push_back(0);
00263                 assert(texCoordOffset + index < texPtr->size());
00264                 indicesPtr->push_back(texCoordOffset + index);
00265             }
00266             indexBegin = indexEnd;
00267         }
00268 
00269         // add the back and side faces only if depth > 0
00270         if (depth > 0.f)
00271         {
00272             // add the back face to the geometry
00273 
00274             // store positions
00275             // No need to store texture coordinates - we reuse the
00276             // texture coordinates from the front side
00277             UInt32 backCoordOffset = posPtr->size();
00278             coordZ = -0.5f * depth;
00279             for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt)
00280             {
00281                 Vec2f coord = *cIt + pos;
00282                 coord *= scale;
00283                 posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ));
00284             }
00285 
00286             // Store types, lengths and indices
00287             // We have to flip all triangles to enable correct backface culling.
00288             // For GL_TRIANGLES, we simply flip the vertices.
00289             // For GL_TRIANGLE_FANs, we leave the first vertex at its place and flip the
00290             // remaining vertices.
00291             // For GL_TRIANGLE_STRIPs, things are more complicated. When the number of
00292             // vertices is uneven, we simply flip the vertices. When the number of
00293             // vertices is even, we have to add an additional vertex before we flip the
00294             // vertices.
00295             vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt;
00296             UInt32 indexBegin = 0, indexEnd;
00297             for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt)
00298             {
00299                 typesPtr->push_back(tIt->first);
00300                 indexEnd = tIt->second;
00301                 assert(indexEnd >= indexBegin);
00302                 UInt32 len = indexEnd - indexBegin;
00303                 UInt32 i = indexEnd;
00304                 if (tIt->first == GL_TRIANGLE_FAN)
00305                 {
00306                     i = indexBegin;
00307                     ++indexBegin;
00308                 }
00309                 if ((tIt->first == GL_TRIANGLE_STRIP) && ((len & 1) == 0))
00310                 {
00311                     assert((indexEnd >= 2) && (indexEnd - 2 >= indexBegin));
00312                     i = indexEnd - 2;
00313                     ++len;
00314                 }
00315                 if (i != indexEnd)
00316                 {
00317                     // the interleaved multi-index blocks have the layout
00318                     // Position | Normal | TexCoord
00319                     assert(i < outline.indices.size());
00320                     UInt32 index = outline.indices[i];
00321                     assert(backCoordOffset + index < posPtr->size());
00322                     indicesPtr->push_back(backCoordOffset + index);
00323                     indicesPtr->push_back(1);
00324                     assert(texCoordOffset + index < texPtr->size());
00325                     indicesPtr->push_back(texCoordOffset + index);
00326                     i = indexEnd;
00327                 }
00328                 lensPtr->push_back(len);
00329                 while (true)
00330                 {
00331                     if (i <= indexBegin)
00332                         break;
00333                     --i;
00334 
00335                     // the interleaved multi-index blocks have the layout
00336                     // Position | Normal | TexCoord
00337                     assert(i < outline.indices.size());
00338                     UInt32 index = outline.indices[i];
00339                     assert(backCoordOffset + index < posPtr->size());
00340                     indicesPtr->push_back(backCoordOffset + index);
00341                     indicesPtr->push_back(1);
00342                     assert(texCoordOffset + index < texPtr->size());
00343                     indicesPtr->push_back(texCoordOffset + index);
00344                 }
00345                 indexBegin = indexEnd;
00346             }
00347 
00348             // Add the side faces to the geometry
00349             const TextVectorGlyph::Normals &normals = glyph.getNormals(level);
00350 
00351             // construct the multi index
00352             UInt32 start = 0, end, index = 0;
00353             vector<UInt32>::const_iterator iIt;
00354             vector<TextVectorGlyph::Orientation>::const_iterator oriIt = glyph.getContourOrientations().begin();
00355             for (iIt = outline.contours.begin(); iIt != outline.contours.end(); ++iIt, ++oriIt)
00356             {
00357                 assert(oriIt != glyph.getContourOrientations().end());
00358                 UInt32 contourCoordOffset, contourBackCoordOffset;
00359                 if (*oriIt == TextVectorGlyph::CCW)
00360                 {
00361                     contourCoordOffset = coordOffset;
00362                     contourBackCoordOffset = backCoordOffset;
00363                 }
00364                 else
00365                 {
00366                     contourCoordOffset = backCoordOffset;
00367                     contourBackCoordOffset = coordOffset;
00368                 }
00369 
00370                 end = *iIt;
00371 
00372                 // the side faces are stored as quads
00373                 GLenum mode = GL_QUAD_STRIP;
00374                 UInt32 len = 0;
00375 
00376                 UInt32 coordIndex, backCoordIndex;
00377                 UInt32 normalOffset, startNormalOffset = normalsPtr->size();
00378                 for (index = start; index < end; ++index)
00379                 {
00380                     normalOffset = normalsPtr->size() - 1;
00381                     assert(index < normals.size());
00382                     if (normals[index].edgeAngle > creaseAngle)
00383                     {
00384                         // We have an edge with two normals, so we need to
00385                         // add the vertices twice, but with different normals
00386                         // - but only when this is not the start index
00387                         if (index > start)
00388                         {
00389                             if ((mode == GL_QUAD_STRIP) && (len > 2))
00390                             {
00391                                 typesPtr->push_back(GL_QUAD_STRIP);
00392                                 assert(((len + 2) & 1) == 0);
00393                                 lensPtr->push_back(len + 2);
00394                                 len = 0;
00395                                 coordIndex = contourCoordOffset + index;
00396                                 backCoordIndex = contourBackCoordOffset + index;
00397                             }
00398                             else
00399                             {
00400                                 mode = GL_QUADS;
00401                                 len += 2;
00402                                 coordIndex = contourBackCoordOffset + index;
00403                                 backCoordIndex = contourCoordOffset + index;
00404                             }
00405 
00406                             // back
00407                             assert(backCoordIndex < posPtr->size());
00408                             indicesPtr->push_back(backCoordIndex);
00409                             assert(normalOffset < normalsPtr->size());
00410                             indicesPtr->push_back(normalOffset);
00411                             assert(texCoordOffset + index < texPtr->size());
00412                             indicesPtr->push_back(texCoordOffset + index);
00413                             // front
00414                             assert(coordIndex < posPtr->size());
00415                             indicesPtr->push_back(coordIndex);
00416                             assert(normalOffset < normalsPtr->size());
00417                             indicesPtr->push_back(normalOffset);
00418                             assert(texCoordOffset + index < texPtr->size());
00419                             indicesPtr->push_back(texCoordOffset + index);
00420                         }
00421 
00422                         const Vec2f &normal = normals[index].nextEdgeNormal;
00423                         normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f));
00424                     }
00425                     else
00426                     {
00427                         if (mode == GL_QUADS)
00428                         {
00429                             typesPtr->push_back(GL_QUADS);
00430                             mode = GL_QUAD_STRIP;
00431                             assert(len >= 6);
00432                             assert(((len - 2) & 3) == 0);
00433                             lensPtr->push_back(len - 2);
00434                             len = 2;
00435                         }
00436 
00437                         const Vec2f &normal = normals[index].meanEdgeNormal;
00438                         normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f));
00439                     }
00440                     ++normalOffset;
00441 
00442                     // back
00443                     assert(contourBackCoordOffset + index < posPtr->size());
00444                     indicesPtr->push_back(contourBackCoordOffset + index);
00445                     assert(normalOffset < normalsPtr->size());
00446                     indicesPtr->push_back(normalOffset);
00447                     assert(texCoordOffset + index < texPtr->size());
00448                     indicesPtr->push_back(texCoordOffset + index);
00449                     // front
00450                     assert(contourCoordOffset + index < posPtr->size());
00451                     indicesPtr->push_back(contourCoordOffset + index);
00452                     assert(normalOffset < normalsPtr->size());
00453                     indicesPtr->push_back(normalOffset);
00454                     assert(texCoordOffset + index < texPtr->size());
00455                     indicesPtr->push_back(texCoordOffset + index);
00456 
00457                     len += 2;
00458                 }
00459 
00460                 // We have to close the strip, so add the start vertices again
00461                 if (normals[start].edgeAngle <= creaseAngle)
00462                     normalOffset = startNormalOffset;
00463                 if (mode == GL_QUAD_STRIP)
00464                 {
00465                     coordIndex = contourCoordOffset + start;
00466                     backCoordIndex = contourBackCoordOffset + start;
00467                 }
00468                 else
00469                 {
00470                     coordIndex = contourBackCoordOffset + start;
00471                     backCoordIndex = contourCoordOffset + start;
00472                 }
00473 
00474                 // back
00475                 assert(backCoordIndex < posPtr->size());
00476                 indicesPtr->push_back(backCoordIndex);
00477                 assert(normalOffset < normalsPtr->size());
00478                 indicesPtr->push_back(normalOffset);
00479                 assert(texCoordOffset + start < texPtr->size());
00480                 indicesPtr->push_back(texCoordOffset + start);
00481                 // front
00482                 assert(coordIndex < posPtr->size());
00483                 indicesPtr->push_back(coordIndex);
00484                 assert(normalOffset < normalsPtr->size());
00485                 indicesPtr->push_back(normalOffset);
00486                 assert(texCoordOffset + start < texPtr->size());
00487                 indicesPtr->push_back(texCoordOffset + start);
00488 
00489                 len += 2;
00490 
00491                 // store the number of multi index blocks
00492                 typesPtr->push_back(mode);
00493                 assert((mode != GL_QUADS) || ((len & 3) == 0));
00494                 assert((mode != GL_QUAD_STRIP) || ((len & 1) == 0));
00495                 lensPtr->push_back(len);
00496 
00497                 start = end;
00498             }
00499         }
00500     }
00501 
00502     endEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
00503     endEditCP(indicesPtr, GeoIndicesUI32::GeoPropDataFieldMask);
00504     endEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
00505     endEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
00506     endEditCP(normalsPtr, GeoNormals3f::GeoPropDataFieldMask);
00507     endEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
00508 
00509     endEditCP(geoPtr);
00510 }
00511 
00512 
00513 //----------------------------------------------------------------------
00514 // Creates a new text geometry
00515 // Author: pdaehne
00516 //----------------------------------------------------------------------
00517 GeometryPtr TextVectorFace::makeGeo(const TextLayoutResult &layoutResult, Real32 scale,
00518                                     Real32 depth, UInt32 level, Real32 creaseAngle)
00519 {
00520     GeometryPtr geo = Geometry::create();
00521     fillGeo(geo, layoutResult, scale, depth, level, creaseAngle);
00522     return geo;
00523 }
00524 
00525 
00526 //----------------------------------------------------------------------
00527 // Creates a new node with a text geometry
00528 // Author: pdaehne
00529 //----------------------------------------------------------------------
00530 NodePtr TextVectorFace::makeNode(const TextLayoutResult &layoutResult, Real32 scale,
00531                                  Real32 depth, UInt32 level, Real32 creaseAngle)
00532 {
00533     GeometryPtr geo = makeGeo(layoutResult, scale, depth, level, creaseAngle);
00534     NodePtr node = Node::create();
00535     beginEditCP(node, Node::CoreFieldMask);
00536     node->setCore(geo);
00537     endEditCP(node, Node::CoreFieldMask);
00538     return node;
00539 }
00540 
00541 
00542 //----------------------------------------------------------------------
00543 // Tries to create a vector face
00544 // Author: pdaehne
00545 //----------------------------------------------------------------------
00546 TextVectorFace *TextVectorFace::create(const std::string &family, Style style)
00547 { return TextFaceFactory::the().createVectorFace(family, style); }
00548 
00549 
00550 OSG_END_NAMESPACE
00551 
00552 
00553 /*------------------------------------------------------------------------*/
00554 /*                              cvs id's                                  */
00555 
00556 #ifdef OSG_SGI_CC
00557 #pragma set woff 1174
00558 #endif
00559 
00560 #ifdef OSG_LINUX_ICC
00561 #pragma warning( disable : 177 )
00562 #endif
00563 
00564 namespace
00565 {
00566     static OSG::Char8 cvsid_cpp[] = "@(#)$Id: OSGTextVectorFace.cpp,v 1.2 2005/04/12 14:43:41 jbehr Exp $";
00567     static OSG::Char8 cvsid_hpp[] = OSGTEXTVECTORFACE_HEADER_CVSID;
00568     static OSG::Char8 cvsid_inl[] = OSGTEXTVECTORFACE_INLINE_CVSID;
00569 }
00570 
00571 #ifdef __sgi
00572 #pragma reset woff 1174
00573 #endif

Generated on Thu Aug 25 04:11:38 2005 for OpenSG by  doxygen 1.4.3