Merge remote-tracking branch 'origin/master'
commit
765401531d
@ -0,0 +1,316 @@
|
|||||||
|
#include "stats.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include <osg/PolygonMode>
|
||||||
|
|
||||||
|
#include <osgText/Text>
|
||||||
|
|
||||||
|
#include <osgViewer/Viewer>
|
||||||
|
#include <osgViewer/Renderer>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
|
||||||
|
StatsHandler::StatsHandler():
|
||||||
|
_key(osgGA::GUIEventAdapter::KEY_F4),
|
||||||
|
_initialized(false),
|
||||||
|
_statsType(false),
|
||||||
|
_statsWidth(1280.0f),
|
||||||
|
_statsHeight(1024.0f),
|
||||||
|
_font("fonts/arial.ttf"),
|
||||||
|
_characterSize(20.0f)
|
||||||
|
{
|
||||||
|
_camera = new osg::Camera;
|
||||||
|
_camera->getOrCreateStateSet()->setGlobalDefaults();
|
||||||
|
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
||||||
|
_camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||||
|
|
||||||
|
_resourceStatsChildNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
|
||||||
|
{
|
||||||
|
if (ea.getHandled()) return false;
|
||||||
|
|
||||||
|
switch(ea.getEventType())
|
||||||
|
{
|
||||||
|
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||||
|
{
|
||||||
|
if (ea.getKey()== _key)
|
||||||
|
{
|
||||||
|
osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
|
||||||
|
if (!myview) return false;
|
||||||
|
|
||||||
|
osgViewer::ViewerBase* viewer = myview->getViewerBase();
|
||||||
|
|
||||||
|
toggle(viewer);
|
||||||
|
|
||||||
|
aa.requestRedraw();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case osgGA::GUIEventAdapter::RESIZE:
|
||||||
|
{
|
||||||
|
setWindowSize(ea.getWindowWidth(), ea.getWindowHeight());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsHandler::setWindowSize(int width, int height)
|
||||||
|
{
|
||||||
|
if (width <= 0 || height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_camera->setViewport(0, 0, width, height);
|
||||||
|
if (fabs(height*_statsWidth) <= fabs(width*_statsHeight))
|
||||||
|
{
|
||||||
|
_camera->setProjectionMatrix(osg::Matrix::ortho2D(_statsWidth - width*_statsHeight/height, _statsWidth,0.0,_statsHeight));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,_statsHeight-height*_statsWidth/width,_statsHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsHandler::toggle(osgViewer::ViewerBase *viewer)
|
||||||
|
{
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
setUpHUDCamera(viewer);
|
||||||
|
setUpScene(viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_statsType = !_statsType;
|
||||||
|
|
||||||
|
if (!_statsType)
|
||||||
|
{
|
||||||
|
_camera->setNodeMask(0);
|
||||||
|
_switch->setAllChildrenOff();
|
||||||
|
|
||||||
|
viewer->getViewerStats()->collectStats("resource", false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_camera->setNodeMask(0xffffffff);
|
||||||
|
_switch->setSingleChildOn(_resourceStatsChildNum);
|
||||||
|
|
||||||
|
viewer->getViewerStats()->collectStats("resource", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
|
||||||
|
{
|
||||||
|
// Try GraphicsWindow first so we're likely to get the main viewer window
|
||||||
|
osg::GraphicsContext* context = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
{
|
||||||
|
osgViewer::Viewer::Windows windows;
|
||||||
|
viewer->getWindows(windows);
|
||||||
|
|
||||||
|
if (!windows.empty()) context = windows.front();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No GraphicsWindows were found, so let's try to find a GraphicsContext
|
||||||
|
context = _camera->getGraphicsContext();
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
{
|
||||||
|
osgViewer::Viewer::Contexts contexts;
|
||||||
|
viewer->getContexts(contexts);
|
||||||
|
|
||||||
|
if (contexts.empty()) return;
|
||||||
|
|
||||||
|
context = contexts.front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_camera->setGraphicsContext(context);
|
||||||
|
|
||||||
|
_camera->setRenderOrder(osg::Camera::POST_RENDER, 11);
|
||||||
|
|
||||||
|
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||||
|
_camera->setViewMatrix(osg::Matrix::identity());
|
||||||
|
setWindowSize(context->getTraits()->width, context->getTraits()->height);
|
||||||
|
|
||||||
|
// only clear the depth buffer
|
||||||
|
_camera->setClearMask(0);
|
||||||
|
_camera->setAllowEventFocus(false);
|
||||||
|
|
||||||
|
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color)
|
||||||
|
{
|
||||||
|
osg::StateSet *ss = new osg::StateSet;
|
||||||
|
|
||||||
|
osg::Geometry* geometry = new osg::Geometry;
|
||||||
|
|
||||||
|
geometry->setUseDisplayList(false);
|
||||||
|
geometry->setStateSet(ss);
|
||||||
|
|
||||||
|
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||||
|
geometry->setVertexArray(vertices);
|
||||||
|
|
||||||
|
vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x(), pos.y()-height,0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x()+width, pos.y()-height,0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x()+width, pos.y(),0));
|
||||||
|
|
||||||
|
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||||
|
colors->push_back(color);
|
||||||
|
geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
|
||||||
|
|
||||||
|
osg::DrawElementsUShort *base = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_FAN,0);
|
||||||
|
base->push_back(0);
|
||||||
|
base->push_back(1);
|
||||||
|
base->push_back(2);
|
||||||
|
base->push_back(3);
|
||||||
|
|
||||||
|
geometry->addPrimitiveSet(base);
|
||||||
|
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResourceStatsTextDrawCallback : public osg::Drawable::DrawCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceStatsTextDrawCallback(osg::Stats* stats, const std::vector<std::string>& statNames)
|
||||||
|
: _stats(stats)
|
||||||
|
, _statNames(statNames)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
||||||
|
{
|
||||||
|
if (!_stats) return;
|
||||||
|
|
||||||
|
osgText::Text* text = (osgText::Text*)(drawable);
|
||||||
|
|
||||||
|
std::ostringstream viewStr;
|
||||||
|
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
||||||
|
viewStr.width(14);
|
||||||
|
// Used fixed formatting, as scientific will switch to "...e+.." notation for
|
||||||
|
// large numbers of vertices/drawables/etc.
|
||||||
|
viewStr.setf(std::ios::fixed);
|
||||||
|
viewStr.precision(0);
|
||||||
|
|
||||||
|
unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber()-1;
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator it = _statNames.begin(); it != _statNames.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->empty())
|
||||||
|
viewStr << std::endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double value = 0.0;
|
||||||
|
if (_stats->getAttribute(frameNumber, *it, value))
|
||||||
|
viewStr << std::setw(8) << value << std::endl;
|
||||||
|
else
|
||||||
|
viewStr << std::setw(8) << "." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text->setText(viewStr.str());
|
||||||
|
|
||||||
|
text->drawImplementation(renderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Stats> _stats;
|
||||||
|
std::vector<std::string> _statNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
|
||||||
|
{
|
||||||
|
_switch = new osg::Switch;
|
||||||
|
|
||||||
|
_camera->addChild(_switch);
|
||||||
|
|
||||||
|
osg::StateSet* stateset = _switch->getOrCreateStateSet();
|
||||||
|
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||||
|
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||||
|
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
|
||||||
|
#ifdef OSG_GL1_AVAILABLE
|
||||||
|
stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
osg::Vec3 pos(_statsWidth-300.f, _statsHeight-500.0f,0.0f);
|
||||||
|
osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3);
|
||||||
|
osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0);
|
||||||
|
osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0);
|
||||||
|
float backgroundMargin = 5;
|
||||||
|
float backgroundSpacing = 3;
|
||||||
|
|
||||||
|
// resource stats
|
||||||
|
{
|
||||||
|
osg::Group* group = new osg::Group;
|
||||||
|
group->setCullingActive(false);
|
||||||
|
_resourceStatsChildNum = _switch->getNumChildren();
|
||||||
|
_switch->addChild(group, false);
|
||||||
|
|
||||||
|
const char* statNames[] = {"Compiling", "WorkQueue", "WorkThread", "", "Node", "Node Instance", "Shape", "Shape Instance", "Image", "Nif", "Keyframe", "Terrain Cell", "Terrain Texture", "", "UnrefQueue"};
|
||||||
|
|
||||||
|
int numLines = sizeof(statNames) / sizeof(statNames[0]);
|
||||||
|
|
||||||
|
group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
||||||
|
10 * _characterSize + 2 * backgroundMargin,
|
||||||
|
numLines * _characterSize + 2 * backgroundMargin,
|
||||||
|
backgroundColor));
|
||||||
|
|
||||||
|
osg::ref_ptr<osgText::Text> staticText = new osgText::Text;
|
||||||
|
group->addChild( staticText.get() );
|
||||||
|
staticText->setColor(staticTextColor);
|
||||||
|
staticText->setFont(_font);
|
||||||
|
staticText->setCharacterSize(_characterSize);
|
||||||
|
staticText->setPosition(pos);
|
||||||
|
|
||||||
|
std::ostringstream viewStr;
|
||||||
|
viewStr.clear();
|
||||||
|
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
||||||
|
viewStr.width(14);
|
||||||
|
for (size_t i = 0; i<sizeof(statNames)/sizeof(statNames[0]); ++i)
|
||||||
|
{
|
||||||
|
viewStr << statNames[i] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticText->setText(viewStr.str());
|
||||||
|
|
||||||
|
pos.x() += 10 * _characterSize + 2 * backgroundMargin + backgroundSpacing;
|
||||||
|
|
||||||
|
group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
||||||
|
5 * _characterSize + 2 * backgroundMargin,
|
||||||
|
numLines * _characterSize + 2 * backgroundMargin,
|
||||||
|
backgroundColor));
|
||||||
|
|
||||||
|
osg::ref_ptr<osgText::Text> statsText = new osgText::Text;
|
||||||
|
group->addChild( statsText.get() );
|
||||||
|
|
||||||
|
statsText->setColor(dynamicTextColor);
|
||||||
|
statsText->setFont(_font);
|
||||||
|
statsText->setCharacterSize(_characterSize);
|
||||||
|
statsText->setPosition(pos);
|
||||||
|
statsText->setText("");
|
||||||
|
statsText->setDrawCallback(new ResourceStatsTextDrawCallback(viewer->getViewerStats(), std::vector<std::string>(statNames, statNames + numLines)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StatsHandler::getUsage(osg::ApplicationUsage &usage) const
|
||||||
|
{
|
||||||
|
usage.addKeyboardMouseBinding(_key, "On screen resource usage stats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
#ifndef OPENMW_COMPONENTS_RESOURCE_STATS_H
|
||||||
|
#define OPENMW_COMPONENTS_RESOURCE_STATS_H
|
||||||
|
|
||||||
|
#include <osgGA/GUIEventHandler>
|
||||||
|
|
||||||
|
namespace osgViewer
|
||||||
|
{
|
||||||
|
class ViewerBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Switch;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
|
||||||
|
class StatsHandler : public osgGA::GUIEventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StatsHandler();
|
||||||
|
|
||||||
|
void setKey(int key) { _key = key; }
|
||||||
|
int getKey() const { return _key; }
|
||||||
|
|
||||||
|
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
|
||||||
|
|
||||||
|
void setWindowSize(int w, int h);
|
||||||
|
|
||||||
|
void toggle(osgViewer::ViewerBase* viewer);
|
||||||
|
|
||||||
|
void setUpHUDCamera(osgViewer::ViewerBase* viewer);
|
||||||
|
void setUpScene(osgViewer::ViewerBase* viewer);
|
||||||
|
|
||||||
|
/** Get the keyboard and mouse usage of this manipulator.*/
|
||||||
|
virtual void getUsage(osg::ApplicationUsage& usage) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<osg::Switch> _switch;
|
||||||
|
int _key;
|
||||||
|
osg::ref_ptr<osg::Camera> _camera;
|
||||||
|
bool _initialized;
|
||||||
|
bool _statsType;
|
||||||
|
|
||||||
|
float _statsWidth;
|
||||||
|
float _statsHeight;
|
||||||
|
|
||||||
|
std::string _font;
|
||||||
|
float _leftPos;
|
||||||
|
float _characterSize;
|
||||||
|
|
||||||
|
int _resourceStatsChildNum;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue