/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include using namespace osgText; struct FadeTextData : public osg::Referenced { FadeTextData(FadeText* fadeText=0): _fadeText(fadeText), _visible(true) {} bool operator < (const FadeTextData& rhs) const { return _fadeText < rhs._fadeText; } double getNearestZ() const { double nearestZ = _vertices[0].z(); if (nearestZ < _vertices[1].z()) nearestZ = _vertices[1].z(); if (nearestZ < _vertices[2].z()) nearestZ = _vertices[2].z(); if (nearestZ < _vertices[3].z()) nearestZ = _vertices[3].z(); // osg::notify(osg::NOTICE)<<"getNearestZ()="<<_fadeText->getText().createUTF8EncodedString()<<" "<0.0f; normalFrontFace.normalize(); add(osg::Plane(normalFrontFace, _vertices[0])); add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[0], _vertices[1])); add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[1], _vertices[2])); add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[2], _vertices[3])); add(osg::Plane( osg::Vec3d(0.0f,0.0f,0.0f), _vertices[3], _vertices[0])); #if 0 osg::notify(osg::NOTICE)<<" normalFrontFace = "<& vertices) { for(std::vector::const_iterator itr = vertices.begin(); itr != vertices.end(); ++itr) { if (osg::Polytope::contains(*itr)) { return true; } } return false; } }; struct FadeTextUserData : public osg::Referenced { FadeTextUserData(): _frameNumber(0) {} typedef std::list FadeTextList; unsigned int _frameNumber; FadeTextList _fadeTextInView; }; struct GlobalFadeText : public osg::Referenced { typedef std::set< osg::ref_ptr > UserDataSet; typedef std::set FadeTextSet; typedef std::multimap > FadeTextPolytopeMap; typedef std::map ViewUserDataMap; typedef std::map ViewFadeTextMap; GlobalFadeText(): _frameNumber(0xffffffff) { } FadeTextUserData* createNewFadeTextUserData(osg::View* view) { OpenThreads::ScopedLock lock(_mutex); FadeTextUserData* userData = new FadeTextUserData; if (!userData) { osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<first; FadeTextSet& fadeTextSet = _viewFadeTextMap[view]; fadeTextSet.clear(); FadeTextPolytopeMap fadeTextPolytopeMap; for(GlobalFadeText::UserDataSet::iterator uitr = vitr->second.begin(); uitr != vitr->second.end(); ++uitr) { FadeTextUserData* userData = uitr->get(); int frameDelta = frameNumber - userData->_frameNumber; if (frameDelta<=1) { for(FadeTextUserData::FadeTextList::iterator fitr = userData->_fadeTextInView.begin(); fitr != userData->_fadeTextInView.end(); ++fitr) { FadeTextData& fadeTextData = *fitr; if (fadeTextSet.count(fadeTextData._fadeText)==0) { fadeTextSet.insert(fadeTextData._fadeText); fadeTextPolytopeMap.insert(FadeTextPolytopeMap::value_type( -fadeTextData.getNearestZ(), new FadeTextPolytopeData(fadeTextData))); } } } } // for each FadeTexPoltopeData // create polytopes // test against all FTPD's later in the list // test all control points on FTPD against each plane of the current polytope // if all control points removed or outside then discard FTPD and make FT visible = false; FadeTextPolytopeMap::iterator outer_itr = fadeTextPolytopeMap.begin(); while (outer_itr != fadeTextPolytopeMap.end()) { FadeTextPolytopeMap::iterator inner_itr = outer_itr; ++inner_itr; if (inner_itr == fadeTextPolytopeMap.end()) break; FadeTextPolytopeData& outer_ftpm = *(outer_itr->second); outer_ftpm.buildPolytope(); // osg::notify(osg::NOTICE)<<"Outer z "<second); // osg::notify(osg::NOTICE)<<"Inner z "< s_globalFadeText = new GlobalFadeText; return s_globalFadeText.get(); } struct FadeText::FadeTextUpdateCallback : public osg::Drawable::UpdateCallback { FadeTextData _ftd; virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable) { osgText::FadeText* fadeText = dynamic_cast(drawable); if (!fadeText) return; unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber(); GlobalFadeText* gft = getGlobalFadeText(); gft->updateIfRequired(frameNumber); osgText::FadeText::ViewBlendColourMap& vbcm = fadeText->getViewBlendColourMap(); _ftd._fadeText = fadeText; float fadeSpeed = fadeText->getFadeSpeed(); GlobalFadeText::ViewFadeTextMap& vftm = gft->_viewFadeTextMap; for(GlobalFadeText::ViewFadeTextMap::iterator itr = vftm.begin(); itr != vftm.end(); ++itr) { osg::View* view = itr->first; GlobalFadeText::FadeTextSet& fadeTextSet = itr->second; bool visible = fadeTextSet.count(fadeText)!=0; osg::Vec4& tec = vbcm[view]; tec[0] = 1.0f; tec[1] = 1.0f; tec[2] = 1.0f; if (visible) { if (tec[3]<1.0f) { tec[3] += fadeSpeed; if (tec[3]>1.0f) tec[3] = 1.0f; } } else { if (tec[3]>0.0f) { tec[3] -= fadeSpeed; if (tec[3]<0.0f) tec[3] = 0.0f; } } } } }; FadeText::FadeText() { init(); } FadeText::FadeText(const Text& text,const osg::CopyOp& copyop): Text(text,copyop) { init(); } void FadeText::init() { _fadeSpeed = 0.01f; setUpdateCallback(new FadeTextUpdateCallback()); } void FadeText::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State& state = *renderInfo.getState(); ViewBlendColourMap::iterator itr = _viewBlendColourMap.find(renderInfo.getView()); if (itr != _viewBlendColourMap.end()) { Text::drawImplementation(*renderInfo.getState(), itr->second ); } else { Text::drawImplementation(*renderInfo.getState(), osg::Vec4(1.0f,1.0f,1.0f,1.0f) ); } // now pass on new details FadeTextUserData* userData = dynamic_cast(renderInfo.getUserData()); if (!userData) { if (renderInfo.getUserData()) { osg::notify(osg::NOTICE)<<"Warning user data not of supported type."<createNewFadeTextUserData(renderInfo.getView()); if (!userData) { osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<getFrameStamp()->getFrameNumber(); if (frameNumber != userData->_frameNumber) { // new frame so must reset UserData structure. userData->_frameNumber = frameNumber; userData->_fadeTextInView.clear(); } osgText::Text::AutoTransformCache& atc = _autoTransformCache[renderInfo.getContextID()]; osg::Matrix lmv = atc._matrix; lmv.postMult(state.getModelViewMatrix()); if (renderInfo.getView() && renderInfo.getView()->getCamera()) { // move from camera into the view space. lmv.postMult(state.getInitialInverseViewMatrix()); lmv.postMult(renderInfo.getView()->getCamera()->getViewMatrix()); } FadeTextData ftd(const_cast(this)); ftd._vertices[0].set(osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv); ftd._vertices[1].set(osg::Vec3d(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv); ftd._vertices[2].set(osg::Vec3d(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv); ftd._vertices[3].set(osg::Vec3d(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv); userData->_fadeTextInView.push_back(ftd); }