Added panning and zooming functionality to transfer function UI prototype code.
This commit is contained in:
parent
80c45ad46a
commit
d7442e7456
@ -1,4 +1,8 @@
|
||||
SET(TARGET_SRC osgtransferfunction.cpp )
|
||||
SET(TARGET_SRC
|
||||
Widget.cpp
|
||||
TransferFunctionWidget.cpp
|
||||
osgtransferfunction.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_ADDED_LIBRARIES osgVolume osgManipulator)
|
||||
|
||||
|
394
examples/osgtransferfunction/TransferFunctionWidget.cpp
Normal file
394
examples/osgtransferfunction/TransferFunctionWidget.cpp
Normal file
@ -0,0 +1,394 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 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 "TransferFunctionWidget.h"
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osgGA/EventVisitor>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgViewer/View>
|
||||
|
||||
using namespace osgUI;
|
||||
|
||||
TransferFunctionWidget::TransferFunctionWidget(osg::TransferFunction1D* tf):
|
||||
_min(FLT_MAX),
|
||||
_max(-FLT_MAX),
|
||||
_left(FLT_MAX),
|
||||
_right(-FLT_MAX),
|
||||
_startedDrag(false),
|
||||
_previousDragPosition(0.0f)
|
||||
{
|
||||
setNumChildrenRequiringEventTraversal(1);
|
||||
setExtents(osg::BoundingBox(0.0,0.0,0.0,1.0,1.0,0.0));
|
||||
setTransferFunction(tf);
|
||||
}
|
||||
|
||||
TransferFunctionWidget::TransferFunctionWidget(const TransferFunctionWidget& tfw, const osg::CopyOp& copyop):
|
||||
Widget(tfw,copyop)
|
||||
{
|
||||
setExtents(tfw.getExtents());
|
||||
setTransferFunction(tfw.getTransferFunction());
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::setTransferFunction(const osg::TransferFunction1D* tf)
|
||||
{
|
||||
if (_transferFunction==tf) return;
|
||||
|
||||
_transferFunction = const_cast<osg::TransferFunction1D*>(tf);
|
||||
|
||||
if (_transferFunction.valid())
|
||||
{
|
||||
osg::TransferFunction1D::ColorMap& colorMap = _transferFunction->getColorMap();
|
||||
if (colorMap.empty())
|
||||
{
|
||||
_min = FLT_MAX;
|
||||
_max = -FLT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
_min = colorMap.begin()->first;
|
||||
_max = colorMap.rbegin()->first;
|
||||
}
|
||||
}
|
||||
|
||||
resetVisibleRange();
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::resetVisibleRange()
|
||||
{
|
||||
setVisibleRange(_min, _max);
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::setVisibleRange(float left, float right)
|
||||
{
|
||||
if (left<_min) left = _min;
|
||||
if (right>_max) right = _max;
|
||||
|
||||
_left = left;
|
||||
_right = right;
|
||||
// OSG_NOTICE<<"setVisibleRange("<<_left<<", "<<_right<<")"<<std::endl;
|
||||
createGraphics();
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::translateVisibleRange(float delta)
|
||||
{
|
||||
float new_left = _left+(_right-_left)*delta;
|
||||
float new_right = _right+(_right-_left)*delta;
|
||||
if (delta<0.0)
|
||||
{
|
||||
if (new_left<_min)
|
||||
{
|
||||
new_right += (_min-new_left);
|
||||
new_left = _min;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_right>_max)
|
||||
{
|
||||
new_left += (_max-new_right);
|
||||
new_right = _max;
|
||||
}
|
||||
}
|
||||
|
||||
setVisibleRange(new_left, new_right);
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::scaleVisibleRange(float center, float delta)
|
||||
{
|
||||
float scale = powf(2.0, delta);
|
||||
setVisibleRange(center+(_left-center)*scale,
|
||||
center+(_right-center)*scale);
|
||||
}
|
||||
|
||||
|
||||
void TransferFunctionWidget::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
Widget::traverse(nv);
|
||||
}
|
||||
|
||||
bool TransferFunctionWidget::handle(osgGA::EventVisitor* ev, osgGA::Event* event)
|
||||
{
|
||||
osgGA::GUIEventAdapter* ea = event->asGUIEventAdapter();
|
||||
if (!ea) return false;
|
||||
|
||||
switch(ea->getEventType())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::PUSH):
|
||||
// OSG_NOTICE<<"Pressed button "<<ea->getButton()<<std::endl;
|
||||
_startedDrag = false;
|
||||
if (ea->getButtonMask()==osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
|
||||
{
|
||||
osg::Vec3 position;
|
||||
if (computePositionInLocalCoordinates(ev, ea, position))
|
||||
{
|
||||
_startedDrag = true;
|
||||
_previousDragPosition = position.x();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::RELEASE):
|
||||
// OSG_NOTICE<<"Released button "<<ea->getButton()<<std::endl;
|
||||
_startedDrag = false;
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::DRAG):
|
||||
// OSG_NOTICE<<"Dragged "<<std::endl;
|
||||
if (_startedDrag)
|
||||
{
|
||||
osg::Vec3 position;
|
||||
if (computePositionInLocalCoordinates(ev, ea, position))
|
||||
{
|
||||
float delta = -(position.x()-_previousDragPosition);
|
||||
|
||||
_previousDragPosition = position.x();
|
||||
|
||||
translateVisibleRange(delta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL):
|
||||
{
|
||||
osg::Vec3 position;
|
||||
if (computePositionInLocalCoordinates(ev, ea, position))
|
||||
{
|
||||
float translation = 0.0;
|
||||
float increment = 0.1;
|
||||
float scale = 1.0;
|
||||
float ratio = (1.0f+increment);
|
||||
switch(ea->getScrollingMotion())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::SCROLL_NONE):
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL_LEFT):
|
||||
translation -= increment;
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL_RIGHT):
|
||||
translation += increment;
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL_UP):
|
||||
scale /= ratio;
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL_DOWN):
|
||||
scale *= ratio;
|
||||
break;
|
||||
case(osgGA::GUIEventAdapter::SCROLL_2D):
|
||||
translation = increment*ea->getScrollingDeltaX();
|
||||
scale = powf(ratio, increment*ea->getScrollingDeltaY());
|
||||
break;
|
||||
}
|
||||
float center = _left+(_right-_left)*position.x();
|
||||
// OSG_NOTICE<<"translation = "<<translation<<", scale = "<<scale<<", x="<<position.x()<<", center="<<center<<std::endl;
|
||||
setVisibleRange(translation+center+(_left-center)*scale,
|
||||
translation+center+(_right-center)*scale);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||
{
|
||||
// OSG_NOTICE<<"Pressed key"<<ea->getKey()<<std::endl;
|
||||
float delta = 0.02;
|
||||
if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Left) translateVisibleRange(-delta);
|
||||
else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Right) translateVisibleRange(delta);
|
||||
else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Up) scaleVisibleRange((_left+_right)*0.5f, -delta);
|
||||
else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Down) scaleVisibleRange((_left+_right)*0.5f, delta);
|
||||
break;
|
||||
}
|
||||
case(osgGA::GUIEventAdapter::KEYUP):
|
||||
// OSG_NOTICE<<"Released key"<<ea->getKey()<<std::endl;
|
||||
if (ea->getKey()==' ' ||ea->getKey()==osgGA::GUIEventAdapter::KEY_Home) resetVisibleRange();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TransferFunctionWidget::createGraphics()
|
||||
{
|
||||
// OSG_NOTICE<<"Create graphics"<<std::endl;
|
||||
|
||||
typedef osg::TransferFunction1D::ColorMap ColorMap;
|
||||
ColorMap& colorMap = _transferFunction->getColorMap();
|
||||
if (colorMap.empty()) return;
|
||||
|
||||
float depth = 0.0f;
|
||||
float yMax = 0.0f;
|
||||
|
||||
// find yMax
|
||||
for(ColorMap::iterator itr = colorMap.begin();
|
||||
itr != colorMap.end();
|
||||
++itr)
|
||||
{
|
||||
float y = itr->second[3];
|
||||
if (y>yMax) yMax = y;
|
||||
}
|
||||
|
||||
float xScale = 1.0f/(_right-_left);
|
||||
float xOffset = -_left;
|
||||
float yScale = 1.0f/yMax;
|
||||
|
||||
if (!_geode)
|
||||
{
|
||||
_geode = new osg::Geode;
|
||||
addChild(_geode.get());
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
if (!_geometry)
|
||||
{
|
||||
_geometry = new osg::Geometry;
|
||||
_geometry->setDataVariance(osg::Geometry::DYNAMIC);
|
||||
_geometry->setUseDisplayList(false);
|
||||
_geometry->setUseVertexBufferObjects(false);
|
||||
|
||||
_geode->addDrawable(_geometry.get());
|
||||
|
||||
osg::ref_ptr<osg::StateSet> stateset = _geometry->getOrCreateStateSet();
|
||||
|
||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
|
||||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
|
||||
|
||||
osg::ref_ptr<osg::AlphaFunc> alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.0f);
|
||||
stateset->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
|
||||
|
||||
osg::ref_ptr<osg::Image> image = new osg::Image;
|
||||
image->allocateImage(1,1,1, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
unsigned char* data = image->data();
|
||||
data[0] = 255;
|
||||
data[1] = 255;
|
||||
data[2] = 255;
|
||||
data[3] = 255;
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
|
||||
texture->setImage(image.get());
|
||||
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
|
||||
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
|
||||
texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_BORDER);
|
||||
texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_BORDER);
|
||||
texture->setBorderColor(osg::Vec4(1.0f,1.0f,0.0f,0.0f));
|
||||
|
||||
stateset->setTextureAttribute(0, texture.get());
|
||||
|
||||
osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen;
|
||||
texgen->setMode(osg::TexGen::OBJECT_LINEAR);
|
||||
texgen->setPlane(osg::TexGen::S, osg::Plane(1.0,0.0,0.0,0.0));
|
||||
texgen->setPlane(osg::TexGen::T, osg::Plane(0.0,1.0,0.0,0.0));
|
||||
|
||||
stateset->setTextureAttribute(0, texgen.get());
|
||||
stateset->setTextureMode(0, GL_TEXTURE_GEN_S, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
|
||||
stateset->setTextureMode(0, GL_TEXTURE_GEN_T, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
|
||||
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
|
||||
}
|
||||
|
||||
|
||||
if (!_vertices)
|
||||
{
|
||||
_vertices = new osg::Vec3Array;
|
||||
_geometry->setVertexArray(_vertices.get());
|
||||
}
|
||||
|
||||
if (!_colours)
|
||||
{
|
||||
_colours = new osg::Vec4Array;
|
||||
_geometry->setColorArray(_colours.get(), osg::Array::BIND_PER_VERTEX);
|
||||
}
|
||||
|
||||
osg::Vec4 background_color(1.0f, 1.0f, 1.0f, 0.1f);
|
||||
|
||||
unsigned numColumnsRequired = colorMap.size();
|
||||
_vertices->resize(0);
|
||||
_vertices->reserve(numColumnsRequired*3);
|
||||
for(ColorMap::iterator itr = colorMap.begin();
|
||||
itr != colorMap.end();
|
||||
++itr)
|
||||
{
|
||||
float x = itr->first;
|
||||
osg::Vec4 color = itr->second;
|
||||
|
||||
float y = itr->second[3];
|
||||
color[3] = 1.0f;
|
||||
|
||||
_vertices->push_back(osg::Vec3((x+xOffset)*xScale, 0.0f, depth));
|
||||
_colours->push_back(color);
|
||||
|
||||
_vertices->push_back(osg::Vec3((x+xOffset)*xScale, y*yScale, depth));
|
||||
_colours->push_back(color);
|
||||
|
||||
_vertices->push_back(osg::Vec3((x+xOffset)*xScale, y*yScale, depth));
|
||||
_colours->push_back(background_color);
|
||||
|
||||
_vertices->push_back(osg::Vec3((x+xOffset)*xScale, yMax*yScale, depth));
|
||||
_colours->push_back(background_color);
|
||||
}
|
||||
|
||||
if (!_background_primitives)
|
||||
{
|
||||
_background_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP);
|
||||
_geometry->addPrimitiveSet(_background_primitives.get());
|
||||
}
|
||||
|
||||
if (!_historgram_primitives)
|
||||
{
|
||||
_historgram_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP);
|
||||
_geometry->addPrimitiveSet(_historgram_primitives.get());
|
||||
}
|
||||
|
||||
if (!_outline_primitives)
|
||||
{
|
||||
_outline_primitives = new osg::DrawElementsUShort(GL_LINE_STRIP);
|
||||
_geometry->addPrimitiveSet(_outline_primitives.get());
|
||||
}
|
||||
|
||||
_background_primitives->resize(0);
|
||||
_historgram_primitives->resize(0);
|
||||
_outline_primitives->resize(0);
|
||||
|
||||
for(unsigned int i=0; i<numColumnsRequired; ++i)
|
||||
{
|
||||
int iv = i*4;
|
||||
|
||||
_background_primitives->push_back(iv+3);
|
||||
_background_primitives->push_back(iv+2);
|
||||
|
||||
_historgram_primitives->push_back(iv+1);
|
||||
_historgram_primitives->push_back(iv+0);
|
||||
|
||||
_outline_primitives->push_back(iv+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static bool first = true;
|
||||
if (first)
|
||||
{
|
||||
osgDB::writeNodeFile(*_geode, "test.osgt");
|
||||
first = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
_geometry->dirtyBound();
|
||||
|
||||
// make sure the general widget geometry/state is created and _graphicsInitialized reset to false
|
||||
Widget::createGraphics();
|
||||
}
|
73
examples/osgtransferfunction/TransferFunctionWidget.h
Normal file
73
examples/osgtransferfunction/TransferFunctionWidget.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 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.
|
||||
*/
|
||||
|
||||
#ifndef OSGUI_TRANSFERFUNCTIONWIDGET
|
||||
#define OSGUI_TRANSFERFUNCTIONWIDGET
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/TransferFunction>
|
||||
|
||||
#include "Widget.h"
|
||||
|
||||
#define OSGUI_EXPORT
|
||||
|
||||
namespace osgUI
|
||||
{
|
||||
|
||||
class OSGUI_EXPORT TransferFunctionWidget : public osgUI::Widget
|
||||
{
|
||||
public:
|
||||
TransferFunctionWidget(osg::TransferFunction1D* tf=0);
|
||||
TransferFunctionWidget(const TransferFunctionWidget& tfw, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
|
||||
META_Node(osgUI, TransferFunctionWidget);
|
||||
|
||||
void traverse(osg::NodeVisitor& nv);
|
||||
|
||||
virtual bool handle(osgGA::EventVisitor* ev, osgGA::Event* event);
|
||||
|
||||
void setTransferFunction(const osg::TransferFunction1D* tf);
|
||||
osg::TransferFunction1D* getTransferFunction() { return _transferFunction.get(); }
|
||||
const osg::TransferFunction1D* getTransferFunction() const { return _transferFunction.get(); }
|
||||
|
||||
void resetVisibleRange();
|
||||
void setVisibleRange(float left, float right);
|
||||
void translateVisibleRange(float delta);
|
||||
void scaleVisibleRange(float center, float delta);
|
||||
|
||||
virtual void createGraphics();
|
||||
|
||||
protected:
|
||||
virtual ~TransferFunctionWidget() {}
|
||||
|
||||
osg::ref_ptr<osg::TransferFunction1D> _transferFunction;
|
||||
|
||||
osg::ref_ptr<osg::Geode> _geode;
|
||||
osg::ref_ptr<osg::Geometry> _geometry;
|
||||
osg::ref_ptr<osg::Vec3Array> _vertices;
|
||||
osg::ref_ptr<osg::Vec4Array> _colours;
|
||||
osg::ref_ptr<osg::DrawElementsUShort> _background_primitives;
|
||||
osg::ref_ptr<osg::DrawElementsUShort> _historgram_primitives;
|
||||
osg::ref_ptr<osg::DrawElementsUShort> _outline_primitives;
|
||||
|
||||
float _min;
|
||||
float _max;
|
||||
float _left;
|
||||
float _right;
|
||||
|
||||
bool _startedDrag;
|
||||
float _previousDragPosition;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
223
examples/osgtransferfunction/Widget.cpp
Normal file
223
examples/osgtransferfunction/Widget.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 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 "Widget.h"
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osgGA/EventVisitor>
|
||||
#include <osgViewer/View>
|
||||
|
||||
using namespace osgUI;
|
||||
|
||||
Widget::Widget():
|
||||
_focusBehaviour(FOCUS_FOLLOWS_POINTER),
|
||||
_hasEventFocus(false),
|
||||
_graphicsInitialized(false)
|
||||
|
||||
{
|
||||
setNumChildrenRequiringEventTraversal(1);
|
||||
}
|
||||
|
||||
Widget::Widget(const Widget& widget, const osg::CopyOp& copyop):
|
||||
osg::Group(),
|
||||
_focusBehaviour(widget._focusBehaviour),
|
||||
_hasEventFocus(false),
|
||||
_graphicsInitialized(false)
|
||||
{
|
||||
setNumChildrenRequiringEventTraversal(1);
|
||||
}
|
||||
|
||||
void Widget::setExtents(const osg::BoundingBox& bb)
|
||||
{
|
||||
_extents = bb;
|
||||
}
|
||||
|
||||
void Widget::updateFocus(osg::NodeVisitor& nv)
|
||||
{
|
||||
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
|
||||
osgViewer::View* view = ev ? dynamic_cast<osgViewer::View*>(ev->getActionAdapter()) : 0;
|
||||
if (ev && view)
|
||||
{
|
||||
osgGA::EventQueue::Events& events = ev->getEvents();
|
||||
for(osgGA::EventQueue::Events::iterator itr = events.begin();
|
||||
itr != events.end();
|
||||
++itr)
|
||||
{
|
||||
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
|
||||
if (ea)
|
||||
{
|
||||
bool previousFocus = _hasEventFocus;
|
||||
if (_focusBehaviour==CLICK_TO_FOCUS)
|
||||
{
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::PUSH)
|
||||
{
|
||||
int numButtonsPressed = 0;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
|
||||
if (numButtonsPressed==1)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = view->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
if (withinWidget) _hasEventFocus = true;
|
||||
else _hasEventFocus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_focusBehaviour==FOCUS_FOLLOWS_POINTER)
|
||||
{
|
||||
bool checkWithinWidget = false;
|
||||
if (!_hasEventFocus)
|
||||
{
|
||||
checkWithinWidget = (ea->getEventType()!=osgGA::GUIEventAdapter::FRAME) && ea->getButtonMask()==0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if mouse move or mouse release check to see if mouse still within widget to retain focus
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::MOVE)
|
||||
{
|
||||
checkWithinWidget = true;
|
||||
}
|
||||
else if (ea->getEventType()==osgGA::GUIEventAdapter::RELEASE)
|
||||
{
|
||||
// if no buttons pressed then check
|
||||
if (ea->getButtonMask()==0) checkWithinWidget = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkWithinWidget)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = view->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
|
||||
_hasEventFocus = withinWidget;
|
||||
}
|
||||
}
|
||||
|
||||
if (previousFocus != _hasEventFocus)
|
||||
{
|
||||
if (_hasEventFocus)
|
||||
{
|
||||
enter();
|
||||
#if 0
|
||||
if (view->getCameraManipulator())
|
||||
{
|
||||
view->getCameraManipulator()->finishAnimation();
|
||||
view->requestContinuousUpdate( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setHasEventFocus(bool focus)
|
||||
{
|
||||
if (_hasEventFocus == focus) return;
|
||||
|
||||
_hasEventFocus = focus;
|
||||
|
||||
if (_hasEventFocus) enter();
|
||||
else leave();
|
||||
}
|
||||
|
||||
bool Widget::getHasEventFocus() const
|
||||
{
|
||||
return _hasEventFocus;
|
||||
}
|
||||
|
||||
void Widget::enter()
|
||||
{
|
||||
OSG_NOTICE<<"enter()"<<std::endl;
|
||||
}
|
||||
|
||||
void Widget::leave()
|
||||
{
|
||||
OSG_NOTICE<<"leave()"<<std::endl;
|
||||
}
|
||||
|
||||
void Widget::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (!_graphicsInitialized && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR) createGraphics();
|
||||
|
||||
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
|
||||
osgViewer::View* view = ev ? dynamic_cast<osgViewer::View*>(ev->getActionAdapter()) : 0;
|
||||
if (ev && view)
|
||||
{
|
||||
updateFocus(nv);
|
||||
|
||||
if (getHasEventFocus())
|
||||
{
|
||||
// signify that event has been taken by widget with focus
|
||||
ev->setEventHandled(true);
|
||||
|
||||
osgGA::EventQueue::Events& events = ev->getEvents();
|
||||
for(osgGA::EventQueue::Events::iterator itr = events.begin();
|
||||
itr != events.end();
|
||||
++itr)
|
||||
{
|
||||
handle(ev, itr->get());
|
||||
|
||||
(*itr)->setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Group::traverse(nv);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::handle(osgGA::EventVisitor* /*ev*/, osgGA::Event* /*event*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3& localPosition) const
|
||||
{
|
||||
osgViewer::View* view = ev ? dynamic_cast<osgViewer::View*>(ev->getActionAdapter()) : 0;
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
if (view && view->computeIntersections(*event, ev->getNodePath(), intersections))
|
||||
{
|
||||
localPosition = intersections.begin()->getLocalIntersectPoint();
|
||||
|
||||
return (_extents.contains(localPosition, 1e-6));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Widget::createGraphics()
|
||||
{
|
||||
_graphicsInitialized = true;
|
||||
}
|
||||
|
||||
osg::BoundingSphere Widget::computeBound() const
|
||||
{
|
||||
return osg::BoundingSphere(_extents);
|
||||
}
|
84
examples/osgtransferfunction/Widget.h
Normal file
84
examples/osgtransferfunction/Widget.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 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.
|
||||
*/
|
||||
|
||||
#ifndef OSGUI_WIDGET
|
||||
#define OSGUI_WIDGET
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/BoundingBox>
|
||||
#include <osgGA/Event>
|
||||
#include <osgGA/EventVisitor>
|
||||
|
||||
#define OSGUI_EXPORT
|
||||
|
||||
namespace osgUI
|
||||
{
|
||||
|
||||
class OSGUI_EXPORT Widget : public osg::Group
|
||||
{
|
||||
public:
|
||||
Widget();
|
||||
Widget(const Widget& tfw, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
|
||||
META_Node(osgUI, Widget);
|
||||
|
||||
virtual void traverse(osg::NodeVisitor& nv);
|
||||
|
||||
virtual bool handle(osgGA::EventVisitor* ev, osgGA::Event* event);
|
||||
|
||||
virtual bool computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3& localPosition) const;
|
||||
|
||||
virtual void createGraphics();
|
||||
|
||||
virtual void setExtents(const osg::BoundingBox& bb);
|
||||
const osg::BoundingBox& getExtents() const { return _extents; }
|
||||
|
||||
enum FocusBehaviour
|
||||
{
|
||||
CLICK_TO_FOCUS,
|
||||
FOCUS_FOLLOWS_POINTER,
|
||||
EVENT_DRIVEN_FOCUS_DISABLED
|
||||
};
|
||||
|
||||
void setFocusBehaviour(FocusBehaviour behaviour) { _focusBehaviour = behaviour; }
|
||||
FocusBehaviour getFocusBehaviour() const { return _focusBehaviour; }
|
||||
|
||||
/** update the focus according to events.*/
|
||||
virtual void updateFocus(osg::NodeVisitor& nv);
|
||||
|
||||
/** set whether the widget has focus or not.*/
|
||||
virtual void setHasEventFocus(bool focus);
|
||||
|
||||
/** get whether the widget has focus or not.*/
|
||||
virtual bool getHasEventFocus() const;
|
||||
|
||||
virtual osg::BoundingSphere computeBound() const;
|
||||
|
||||
protected:
|
||||
virtual ~Widget() {}
|
||||
|
||||
/** update any focus related graphics+state to the focused state.*/
|
||||
virtual void enter();
|
||||
|
||||
/** update any focus related graphics+state to the unfocused state.*/
|
||||
virtual void leave();
|
||||
|
||||
FocusBehaviour _focusBehaviour;
|
||||
bool _hasEventFocus;
|
||||
bool _graphicsInitialized;
|
||||
|
||||
osg::BoundingBox _extents;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -30,10 +30,15 @@
|
||||
|
||||
#include <osgVolume/Volume>
|
||||
#include <osgVolume/VolumeTile>
|
||||
#include <osgVolume/RayTracedTechnique>
|
||||
#include <osgVolume/FixedFunctionTechnique>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
|
||||
#include "TransferFunctionWidget.h"
|
||||
|
||||
class Histogram
|
||||
{
|
||||
public:
|
||||
@ -248,104 +253,6 @@ osg::Node* Histogram::createGraphicalRepresentation()
|
||||
return transform.release();
|
||||
}
|
||||
|
||||
osg::Node* createGraphicalRepresentation(osg::TransferFunction1D* tf)
|
||||
{
|
||||
typedef osg::TransferFunction1D::ColorMap ColorMap;
|
||||
ColorMap& colorMap = tf->getColorMap();
|
||||
if (colorMap.empty()) return 0;
|
||||
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
|
||||
float xMin = colorMap.begin()->first;
|
||||
float xMax = colorMap.rbegin()->first;
|
||||
|
||||
float depth = 0.0f;
|
||||
float yMax = 0.0f;
|
||||
|
||||
// find yMax
|
||||
for(ColorMap::iterator itr = colorMap.begin();
|
||||
itr != colorMap.end();
|
||||
++itr)
|
||||
{
|
||||
float y = itr->second[3];
|
||||
if (y>yMax) yMax = y;
|
||||
}
|
||||
|
||||
float xScale = 1.0f/(xMax-xMin);
|
||||
float yScale = 1.0f/yMax;
|
||||
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
transform->addChild(geode.get());
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
geode->addDrawable(geometry.get());
|
||||
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
geometry->setVertexArray(vertices.get());
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> colours = new osg::Vec4Array;
|
||||
geometry->setColorArray(colours.get(), osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
osg::Vec4 background_color(1.0f, 1.0f, 1.0f, 0.1f);
|
||||
|
||||
unsigned numColumnsRequired = colorMap.size();
|
||||
vertices->reserve(numColumnsRequired*3);
|
||||
for(ColorMap::iterator itr = colorMap.begin();
|
||||
itr != colorMap.end();
|
||||
++itr)
|
||||
{
|
||||
float x = itr->first;
|
||||
osg::Vec4 color = itr->second;
|
||||
|
||||
float y = itr->second[3];
|
||||
color[3] = 1.0f;
|
||||
|
||||
vertices->push_back(osg::Vec3(x*xScale, 0.0f, depth));
|
||||
colours->push_back(color);
|
||||
|
||||
vertices->push_back(osg::Vec3(x*xScale, y*yScale, depth));
|
||||
colours->push_back(color);
|
||||
|
||||
vertices->push_back(osg::Vec3(x*xScale, y*yScale, depth));
|
||||
colours->push_back(background_color);
|
||||
|
||||
vertices->push_back(osg::Vec3(x*xScale, yMax*yScale, depth));
|
||||
colours->push_back(background_color);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::DrawElementsUShort> background_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP);
|
||||
osg::ref_ptr<osg::DrawElementsUShort> historgram_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP);
|
||||
osg::ref_ptr<osg::DrawElementsUShort> outline_primitives = new osg::DrawElementsUShort(GL_LINE_STRIP);
|
||||
for(unsigned int i=0; i<numColumnsRequired; ++i)
|
||||
{
|
||||
int iv = i*4;
|
||||
|
||||
background_primitives->push_back(iv+3);
|
||||
background_primitives->push_back(iv+2);
|
||||
|
||||
historgram_primitives->push_back(iv+1);
|
||||
historgram_primitives->push_back(iv+0);
|
||||
|
||||
outline_primitives->push_back(iv+1);
|
||||
|
||||
}
|
||||
|
||||
geometry->addPrimitiveSet(outline_primitives.get());
|
||||
geometry->addPrimitiveSet(historgram_primitives.get());
|
||||
geometry->addPrimitiveSet(background_primitives.get());
|
||||
}
|
||||
|
||||
//transform->setMatrix(osg::Matrix::scale(xScale/(maxX-minY), yScale/(yMax), 1.0f));
|
||||
|
||||
transform->setMatrix(osg::Matrix::scale(2.0,1.0,1.0)*osg::Matrix::rotate(osg::DegreesToRadians(90.0), osg::Vec3d(1.0,0.0,0.0)));
|
||||
|
||||
return transform.release();
|
||||
}
|
||||
|
||||
|
||||
osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename, float colorScale=1.0f)
|
||||
{
|
||||
std::string foundFile = osgDB::findDataFile(filename);
|
||||
@ -461,17 +368,72 @@ int main(int argc, char ** argv)
|
||||
|
||||
osgViewer::Viewer viewer(arguments);
|
||||
|
||||
viewer.addEventHandler(new osgViewer::StatsHandler());
|
||||
|
||||
osg::ref_ptr<osg::TransferFunction1D> tf;
|
||||
std::string filename;
|
||||
if (arguments.read("--tf",filename))
|
||||
{
|
||||
tf = readTransferFunctionFile(filename);
|
||||
tf = readTransferFunctionFile(filename, 1.0f);
|
||||
}
|
||||
if (arguments.read("--tf-255",filename))
|
||||
{
|
||||
tf = readTransferFunctionFile(filename,1.0f/255.0f);
|
||||
}
|
||||
|
||||
bool createHistorgram = arguments.read("--histogram");
|
||||
|
||||
osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
|
||||
#if 0
|
||||
for(int i=1; i<arguments.argc(); ++i)
|
||||
{
|
||||
if (!arguments.isOption(i))
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image;
|
||||
osg::ref_ptr<osgVolume::Volume> volume;
|
||||
osg::ref_ptr<osgVolume::VolumeTile> volumeTile;
|
||||
|
||||
std::string filename = arguments[i];
|
||||
osgDB::FileType fileType = osgDB::fileType(foundFile);
|
||||
|
||||
if (fileType == osgDB::DIRECTORY)
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(foundFile+".dicom", options.get());
|
||||
}
|
||||
else if (fileType == osgDB::REGULAR_FILE)
|
||||
{
|
||||
std::string ext = osgDB::getFileExtension(foundFile);
|
||||
if (ext=="osg" || ext=="ive" || ext=="osgx" || ext=="osgb" || ext=="osgt")
|
||||
{
|
||||
osg::ref_ptr<osg::Object> obj = osgDB::readObjectFile(foundFile);
|
||||
image = dynamic_cast<osg::Image*>(obj.get());
|
||||
volume = dynamic_cast<osgVolume::Volume*>(obj.get());
|
||||
volumeTile = dynamic_cast<osgVolume::VolumeTile*>(obj.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
image = osgDB::readImageFile( foundFile );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not found image, so fallback to plugins/callbacks to find the model.
|
||||
image = osgDB::readImageFile( filename);
|
||||
}
|
||||
|
||||
if (image.valid())
|
||||
{
|
||||
volumeTile = new osgVolume::VolumeTile;
|
||||
}
|
||||
|
||||
}
|
||||
OSG_NOTICE<<"Argument "<<i<<" "<<arguments[i]<<std::endl;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
|
||||
osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
|
||||
#endif
|
||||
typedef std::vector< osg::ref_ptr<osg::Node> > Nodes;
|
||||
Nodes nodes;
|
||||
|
||||
@ -493,6 +455,9 @@ int main(int argc, char ** argv)
|
||||
osg::ref_ptr<osgVolume::Volume> volume = new osgVolume::Volume;
|
||||
volume->addChild(model.get());
|
||||
model = volume.get();
|
||||
|
||||
// volumeTile->setVolumeTechnique(new osgVolume::RayTracedTechnique);
|
||||
// volumeTile->setVolumeTechnique(new osgVolume::FixedFunctionTechnique);
|
||||
}
|
||||
|
||||
nodes.push_back(model.get());
|
||||
@ -500,7 +465,12 @@ int main(int argc, char ** argv)
|
||||
FindVolumeTiles fvt;
|
||||
model->accept(fvt);
|
||||
|
||||
if (!fvt._tiles.empty()) imageLayer = dynamic_cast<osgVolume::ImageLayer*>(fvt._tiles[0]->getLayer());
|
||||
if (!fvt._tiles.empty())
|
||||
{
|
||||
osgVolume::VolumeTile* tile = fvt._tiles[0].get();
|
||||
imageLayer = dynamic_cast<osgVolume::ImageLayer*>(tile->getLayer());
|
||||
tile->addEventCallback(new osgVolume::PropertyAdjustmentCallback());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -549,7 +519,10 @@ int main(int argc, char ** argv)
|
||||
|
||||
if (tf.valid())
|
||||
{
|
||||
nodes.push_back(createGraphicalRepresentation(tf.get()));
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
transform->setMatrix(osg::Matrix::scale(2.0,1.0,1.0)*osg::Matrix::rotate(osg::DegreesToRadians(90.0), osg::Vec3d(1.0,0.0,0.0)));
|
||||
transform->addChild(new osgUI::TransferFunctionWidget(tf.get()));
|
||||
nodes.push_back(transform.get());
|
||||
}
|
||||
|
||||
if (nodes.empty())
|
||||
@ -558,7 +531,10 @@ int main(int argc, char ** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nodes.size()==1) viewer.setSceneData(nodes[0].get());
|
||||
if (nodes.size()==1)
|
||||
{
|
||||
viewer.setSceneData(nodes[0].get());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Vec3d position(0.0,0.0,0.0);
|
||||
@ -594,7 +570,7 @@ int main(int argc, char ** argv)
|
||||
viewer.setSceneData(group.get());
|
||||
}
|
||||
|
||||
|
||||
OSG_NOTICE<<"Reading to run viewer"<<std::endl;
|
||||
|
||||
osgDB::writeNodeFile(*viewer.getSceneData(),"graph.osgt");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user