Hi Robert,
I hope you're not sick of hearing from me yet. I have uncovered a difference
of behavior between 3.4 and 3.6 in osgText::Text's bounding box calculation.
The attached program attempts to demonstrate the difference.
In one place in our application, we are trying to determine the width of a text
string in model coordinates. This works well using getBoundingBox(). The
problem we are seeing is if we change the text string, then call
getBoundingBox() before drawImplementation() has a chance to run, the bounding
box is vastly different than expected. I believe this is because
computePositions() passes in 0 for the osg::State to computeMatrix().
Because of this, it's unclear when we call getBoundingBox if we're getting
model coordinates or screen coordinates. (sorry, I'm not sure if that's the
correct terminology)
In OSG 3.4, if you run the attached program, you'll get the same value printout
before and after change. In OSG 3.6, you get a value that is vastly larger
after. You can see the relevant code in TextWidthPrinter::handle(), and on the
console by pressing 't' at runtime.
This is not a blocker for us because we have access to the osg::State in our
code and can multiply against the correct matrix to value we need. We can #if
OSG_VERSION_GREATER_THAN our code. But this change looks unintentional, so I
wanted to pass along this test program that demonstrates the issue.
I hope this is helpful.
- Dan
/* OpenSceneGraph example, osgtext.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <iostream>
#include <osgDB/ReadFile>
#include <osgGA/StateSetManipulator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/config/SingleWindow>
#include <osg/Camera>
#include <osg/MatrixTransform>
#include <osgText/Font>
#include <osgText/Text>
osgText::Text* createText(const std::string& textString, float xPosition)
{
osgText::Text* returnValue = new osgText::Text;
returnValue->setDataVariance(osg::Object::DYNAMIC);
returnValue->setFont("fonts/times.ttf");
returnValue->setCharacterSize(32.f);
returnValue->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
returnValue->setPosition(osg::Vec3(xPosition, -0.05, 0.0));
returnValue->setAlignment(osgText::TextBase::CENTER_CENTER);
returnValue->setAutoRotateToScreen(true);
returnValue->setText(textString);
// Note that adding a drop shadow makes text's alignment pretty far off.
This does
// not seem to have a huge negative impact in my app, but was noticed
during the copy
// over to this demo. Probably just an artifact of only having text in the
scene?
//returnValue->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
return returnValue;
}
class TextWidthPrinter : public osgGA::GUIEventHandler
{
public:
TextWidthPrinter(osgText::Text* text)
: text_(text)
{
}
virtual bool handle(const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa)
{
if (ea.getEventType() == ea.KEYDOWN && ea.getKey() == 't')
{
// Matrix has -1 as left side as window, +1 as right side of window.
So one
// would expect that this would be approximately 0.44 (~1/4 of screen)
std::cout << "Text width before setText(): " << getTextWidth() << "\n";
// Change the text string, then change it back to old text
const osgText::String oldText = text_->getText();
text_->setText("Anything else");
text_->setText(oldText);
// Demonstrate that the bounding box units are drastically different.
This appears
// to be the actual on-screen text width, not in the model coordinates.
std::cout << "Text width after setText(): " << getTextWidth() << "\n";
return true;
}
return false;
}
/** Returns the bounding box's size in X coordinates */
float getTextWidth() const
{
const osg::BoundingBox bb = text_->getBoundingBox();
return bb.xMax() - bb.xMin();
}
private:
osgText::Text* text_;
};
int main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc, argv);
// construct the viewer.
osgViewer::Viewer viewer(arguments);
// make sure the root node is group so we can add extra nodes to it.
osg::Group* group = new osg::Group;
osgText::Text* testText = createText("Press 't' to test", 0.0);
group->addChild(testText);
// set the scene to render
viewer.setSceneData(group);
viewer.addEventHandler(new
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
viewer.addEventHandler(new TextWidthPrinter(testText));
int width = 800;
int height = 600;
viewer.setUpViewInWindow(100, 100, width, height);
// Configure an ortho-2D projection, using -1 and +1 as bounds
osg::Camera* camera = viewer.getCamera();
camera->getOrCreateStateSet()->setGlobalDefaults();
camera->setProjectionMatrixAsOrtho2D(-1.f, 1.f, -1.f, 1.f);
camera->setProjectionResizePolicy(osg::Camera::FIXED);
camera->setViewMatrixAsLookAt(
osg::Vec3d(0, 0, 100),
osg::Vec3d(0, 0, 0),
osg::Y_AXIS);
viewer.run();
return 0;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org