Added panning and zooming functionality to transfer function UI prototype code.

This commit is contained in:
Robert Osfield 2013-11-18 12:46:00 +00:00
parent 80c45ad46a
commit d7442e7456
6 changed files with 859 additions and 105 deletions

View File

@ -1,4 +1,8 @@
SET(TARGET_SRC osgtransferfunction.cpp )
SET(TARGET_SRC
Widget.cpp
TransferFunctionWidget.cpp
osgtransferfunction.cpp
)
SET(TARGET_ADDED_LIBRARIES osgVolume osgManipulator)

View 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();
}

View 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

View 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);
}

View 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

View File

@ -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");