diff --git a/include/osgText/Text b/include/osgText/Text index 91ee4a895..c32565da8 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -422,6 +422,7 @@ protected: osg::Vec4 _colorGradientBottomRight; osg::Vec4 _colorGradientTopRight; + // Helper function for color interpolation float bilinearInterpolate(float x1, float x2, float y1, float y2, float x, float y, float q11, float q12, float q21, float q22) const; }; diff --git a/include/osgText/Text3D b/include/osgText/Text3D index 124e49045..6b4a5edf5 100644 --- a/include/osgText/Text3D +++ b/include/osgText/Text3D @@ -149,10 +149,6 @@ class OSGTEXT_EXPORT Text3D : public osgText::TextBase osg::ref_ptr _wallStateSet; osg::ref_ptr _backStateSet; - - void setupDecoration(); - - osg::ref_ptr _decorationVertices; }; } diff --git a/include/osgText/TextBase b/include/osgText/TextBase index ec02a0127..5ef342bf1 100644 --- a/include/osgText/TextBase +++ b/include/osgText/TextBase @@ -327,6 +327,11 @@ protected: mutable osg::Vec3 _offset; mutable osg::Vec3 _normal; mutable osg::BoundingBox _textBB; + + void setupDecoration(); + + osg::ref_ptr _decorationVertices; + }; } diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index 9d67a3eaa..4e7bcf508 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -538,6 +538,9 @@ void Text::computeGlyphRepresentation() computeBackdropBoundingBox(); computeBoundingBoxMargin(); computeColorGradients(); + + // set up the vertices for any boundinbox or alignment decoration + setupDecoration(); } // Returns false if there are no glyphs and the width/height values are invalid. @@ -1311,71 +1314,89 @@ void Text::drawImplementation(osg::State& state, const osg::Vec4& colorMultiplie } } - osg::GLBeginEndAdapter& gl = (state.getGLBeginEndAdapter()); state.Normal(_normal.x(), _normal.y(), _normal.z()); - if (_drawMode & FILLEDBOUNDINGBOX) + if ((_drawMode&(~TEXT))!=0) { - if (_textBB.valid()) + + // ** save the previous modelview matrix + osg::Matrix previous(state.getModelViewMatrix()); + + // ** get the modelview for this context + osg::Matrix modelview(_autoTransformCache[contextID]._matrix); + + // ** mult previous by the modelview for this context + modelview.postMult(previous); + + // ** apply this new modelview matrix + state.applyModelViewMatrix(modelview); + + state.disableNormalPointer(); + + state.Color(colorMultiplier.r()*_textBBColor.r(),colorMultiplier.g()*_textBBColor.g(),colorMultiplier.b()*_textBBColor.b(),colorMultiplier.a()*_textBBColor.a()); + + if (_decorationVertices.valid() && !_decorationVertices->empty()) { - #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) - state.applyTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF); + osg::State::ApplyModeProxy applyMode(state, GL_LIGHTING, false); + osg::State::ApplyTextureModeProxy applyTextureMode(state, 0, GL_TEXTURE_2D, false); - const osg::Matrix& matrix = _autoTransformCache[contextID]._matrix; + state.setVertexPointer(_decorationVertices.get()); - osg::Vec3 c00(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix); - osg::Vec3 c10(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*matrix); - osg::Vec3 c11(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*matrix); - osg::Vec3 c01(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix); - - switch(_backdropImplementation) + unsigned int start_index = 0; + if ((_drawMode & FILLEDBOUNDINGBOX)!=0 && _textBB.valid()) { - case NO_DEPTH_BUFFER: - // Do nothing. The bounding box will be rendered before the text and that's all that matters. - break; - case DEPTH_RANGE: - glPushAttrib(GL_DEPTH_BUFFER_BIT); - //unsigned int backdrop_index = 0; - //unsigned int max_backdrop_index = 8; - //const double offset = double(max_backdrop_index - backdrop_index) * 0.003; - glDepthRange(0.001, 1.001); - break; - /*case STENCIL_BUFFER: - break;*/ - default: - glPushAttrib(GL_POLYGON_OFFSET_FILL); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), 10.0f * osg::PolygonOffset::getUnitsMultiplier() ); + #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) + switch(_backdropImplementation) + { + case NO_DEPTH_BUFFER: + // Do nothing. The bounding box will be rendered before the text and that's all that matters. + break; + case DEPTH_RANGE: + glPushAttrib(GL_DEPTH_BUFFER_BIT); + //unsigned int backdrop_index = 0; + //unsigned int max_backdrop_index = 8; + //const double offset = double(max_backdrop_index - backdrop_index) * 0.003; + glDepthRange(0.001, 1.001); + break; + /*case STENCIL_BUFFER: + break;*/ + default: + glPushAttrib(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(0.1f * osg::PolygonOffset::getFactorMultiplier(), 10.0f * osg::PolygonOffset::getUnitsMultiplier() ); + } + + glDrawArrays(GL_QUADS, 0, 4); + start_index += 4; + + switch(_backdropImplementation) + { + case NO_DEPTH_BUFFER: + // Do nothing. + break; + case DEPTH_RANGE: + glDepthRange(0.0, 1.0); + glPopAttrib(); + break; + /*case STENCIL_BUFFER: + break;*/ + default: + glDisable(GL_POLYGON_OFFSET_FILL); + glPopAttrib(); + } + #endif } - gl.Color4f(colorMultiplier.r()*_textBBColor.r(),colorMultiplier.g()*_textBBColor.g(),colorMultiplier.b()*_textBBColor.b(),colorMultiplier.a()*_textBBColor.a()); - gl.Begin(GL_QUADS); - gl.Vertex3fv(c00.ptr()); - gl.Vertex3fv(c10.ptr()); - gl.Vertex3fv(c11.ptr()); - gl.Vertex3fv(c01.ptr()); - gl.End(); - - switch(_backdropImplementation) + if (start_index<_decorationVertices->size()) { - case NO_DEPTH_BUFFER: - // Do nothing. - break; - case DEPTH_RANGE: - glDepthRange(0.0, 1.0); - glPopAttrib(); - break; - /*case STENCIL_BUFFER: - break;*/ - default: - glDisable(GL_POLYGON_OFFSET_FILL); - glPopAttrib(); + state.Color(colorMultiplier.r(),colorMultiplier.g(),colorMultiplier.b(),colorMultiplier.a()); + glDrawArrays(GL_LINES, start_index, _decorationVertices->size()); } - #else - OSG_NOTICE<<"Warning: Text::drawImplementation() fillMode FILLEDBOUNDINGBOX not supported"<empty()) + if ((_drawMode&(~TEXT))!=0) { - state.disableNormalPointer(); - osg::State::ApplyModeProxy applyMode(state, GL_LIGHTING, false); + if (_decorationVertices.valid() && !_decorationVertices->empty()) + { + osg::State::ApplyModeProxy applyMode(state, GL_LIGHTING, false); + osg::State::ApplyTextureModeProxy applyTextureMode(state, 0, GL_TEXTURE_2D, false); - // bool lighting_value = state.getLastAppliedModeValue(GL_LIGHTING); - // if (lighting_value) state.applyMode(GL_LIGHTING, false); + state.setVertexPointer(_decorationVertices.get()); - state.setVertexPointer(_decorationVertices.get()); + unsigned int start_index = 0; + if ((_drawMode & FILLEDBOUNDINGBOX)!=0 && _textBB.valid()) + { + state.Color(_textBBColor.r(),_textBBColor.g(),_textBBColor.b(),_textBBColor.a()); + glDrawArrays(GL_QUADS, 0, 4); + start_index += 4; + } - glDrawArrays(GL_LINES, 0, _decorationVertices->size()); - - ///if (lighting_value) state.applyMode(GL_LIGHTING, true); + if (start_index<_decorationVertices->size()) + { + state.Color(_color.r(),_color.g(),_color.b(),_color.a()); + glDrawArrays(GL_LINES, start_index, _decorationVertices->size()); + } + } } if (_drawMode & TEXT) { - + state.Color(_color.r(),_color.g(),_color.b(),_color.a()); #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE) renderInfo.getState()->applyMode(GL_NORMALIZE, true); @@ -727,96 +735,5 @@ void Text3D::releaseGLObjects(osg::State* state) const if (_font.valid()) _font->releaseGLObjects(state); } - -void Text3D::setupDecoration() -{ - unsigned int numVerticesRequired = 0; - if (_drawMode & BOUNDINGBOX) numVerticesRequired += 24; - if (_drawMode & ALIGNMENT) numVerticesRequired += 4; - - if (numVerticesRequired==0) - { - _decorationVertices = 0; - return; - } - - if (!_decorationVertices) - { - _decorationVertices = new osg::Vec3Array; - _decorationVertices->resize(numVerticesRequired); - } - - _decorationVertices->clear(); - - if ((_drawMode & BOUNDINGBOX)!=0 && _textBB.valid()) - { - osg::Vec3 c000(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); - osg::Vec3 c100(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); - osg::Vec3 c110(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); - osg::Vec3 c010(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); - - osg::Vec3 c001(_textBB.xMin(),_textBB.yMin(),_textBB.zMax()); - osg::Vec3 c101(_textBB.xMax(),_textBB.yMin(),_textBB.zMax()); - osg::Vec3 c111(_textBB.xMax(),_textBB.yMax(),_textBB.zMax()); - osg::Vec3 c011(_textBB.xMin(),_textBB.yMax(),_textBB.zMax()); - - // edges from corner 000 - _decorationVertices->push_back(c000); - _decorationVertices->push_back(c100); - - _decorationVertices->push_back(c000); - _decorationVertices->push_back(c001); - - _decorationVertices->push_back(c000); - _decorationVertices->push_back(c010); - - // edges from corner C101 - _decorationVertices->push_back(c101); - _decorationVertices->push_back(c100); - - _decorationVertices->push_back(c101); - _decorationVertices->push_back(c001); - - _decorationVertices->push_back(c101); - _decorationVertices->push_back(c111); - - - // edges from corner C110 - _decorationVertices->push_back(c110); - _decorationVertices->push_back(c010); - - _decorationVertices->push_back(c110); - _decorationVertices->push_back(c100); - - _decorationVertices->push_back(c110); - _decorationVertices->push_back(c111); - - // edges from corner C011 - _decorationVertices->push_back(c011); - _decorationVertices->push_back(c010); - - _decorationVertices->push_back(c011); - _decorationVertices->push_back(c001); - - _decorationVertices->push_back(c011); - _decorationVertices->push_back(c111); - } - - if (_drawMode & ALIGNMENT) - { - float cursorsize = _characterHeight*0.5f; - - osg::Vec3 hl(osg::Vec3(_offset.x()-cursorsize,_offset.y(),_offset.z())); - osg::Vec3 hr(osg::Vec3(_offset.x()+cursorsize,_offset.y(),_offset.z())); - osg::Vec3 vt(osg::Vec3(_offset.x(),_offset.y()-cursorsize,_offset.z())); - osg::Vec3 vb(osg::Vec3(_offset.x(),_offset.y()+cursorsize,_offset.z())); - - _decorationVertices->push_back(hl); - _decorationVertices->push_back(hr); - _decorationVertices->push_back(vt); - _decorationVertices->push_back(vb); - } -} - } diff --git a/src/osgText/TextBase.cpp b/src/osgText/TextBase.cpp index 88534cf5a..47af2b5d9 100644 --- a/src/osgText/TextBase.cpp +++ b/src/osgText/TextBase.cpp @@ -474,3 +474,129 @@ void TextBase::positionCursor(const osg::Vec2 & endOfLine_coords, osg::Vec2 & cu } } + +void TextBase::setupDecoration() +{ + unsigned int numVerticesRequired = 0; + if (_drawMode & FILLEDBOUNDINGBOX) numVerticesRequired += 4; + if (_drawMode & BOUNDINGBOX) numVerticesRequired += 8; + if (_drawMode & ALIGNMENT) numVerticesRequired += 4; + + if (numVerticesRequired==0) + { + _decorationVertices = 0; + return; + } + + if (!_decorationVertices) + { + _decorationVertices = new osg::Vec3Array; + _decorationVertices->resize(numVerticesRequired); + } + + _decorationVertices->clear(); + + if ((_drawMode & FILLEDBOUNDINGBOX)!=0 && _textBB.valid()) + { + osg::Vec3 c000(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c100(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c110(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); + osg::Vec3 c010(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); + + _decorationVertices->push_back(c000); + _decorationVertices->push_back(c100); + _decorationVertices->push_back(c110); + _decorationVertices->push_back(c010); + } + + if ((_drawMode & BOUNDINGBOX)!=0 && _textBB.valid()) + { + if (_textBB.zMin()==_textBB.zMax()) + { + osg::Vec3 c000(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c100(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c110(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); + osg::Vec3 c010(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); + + _decorationVertices->push_back(c000); + _decorationVertices->push_back(c100); + + _decorationVertices->push_back(c100); + _decorationVertices->push_back(c110); + + _decorationVertices->push_back(c110); + _decorationVertices->push_back(c010); + + _decorationVertices->push_back(c010); + _decorationVertices->push_back(c000); + } + else + { + osg::Vec3 c000(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c100(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); + osg::Vec3 c110(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); + osg::Vec3 c010(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); + + osg::Vec3 c001(_textBB.xMin(),_textBB.yMin(),_textBB.zMax()); + osg::Vec3 c101(_textBB.xMax(),_textBB.yMin(),_textBB.zMax()); + osg::Vec3 c111(_textBB.xMax(),_textBB.yMax(),_textBB.zMax()); + osg::Vec3 c011(_textBB.xMin(),_textBB.yMax(),_textBB.zMax()); + + // edges from corner 000 + _decorationVertices->push_back(c000); + _decorationVertices->push_back(c100); + + _decorationVertices->push_back(c000); + _decorationVertices->push_back(c001); + + _decorationVertices->push_back(c000); + _decorationVertices->push_back(c010); + + // edges from corner C101 + _decorationVertices->push_back(c101); + _decorationVertices->push_back(c100); + + _decorationVertices->push_back(c101); + _decorationVertices->push_back(c001); + + _decorationVertices->push_back(c101); + _decorationVertices->push_back(c111); + + + // edges from corner C110 + _decorationVertices->push_back(c110); + _decorationVertices->push_back(c010); + + _decorationVertices->push_back(c110); + _decorationVertices->push_back(c100); + + _decorationVertices->push_back(c110); + _decorationVertices->push_back(c111); + + // edges from corner C011 + _decorationVertices->push_back(c011); + _decorationVertices->push_back(c010); + + _decorationVertices->push_back(c011); + _decorationVertices->push_back(c001); + + _decorationVertices->push_back(c011); + _decorationVertices->push_back(c111); + } + } + + if (_drawMode & ALIGNMENT) + { + float cursorsize = _characterHeight*0.5f; + + osg::Vec3 hl(osg::Vec3(_offset.x()-cursorsize,_offset.y(),_offset.z())); + osg::Vec3 hr(osg::Vec3(_offset.x()+cursorsize,_offset.y(),_offset.z())); + osg::Vec3 vt(osg::Vec3(_offset.x(),_offset.y()-cursorsize,_offset.z())); + osg::Vec3 vb(osg::Vec3(_offset.x(),_offset.y()+cursorsize,_offset.z())); + + _decorationVertices->push_back(hl); + _decorationVertices->push_back(hr); + _decorationVertices->push_back(vt); + _decorationVertices->push_back(vb); + } +}