目录
1. 作用说明
osgGA::PointerData结构体位于osgGA/GUIEventAdapter 文件,其定义如下:
struct PointerData : public osg::Referenced
{
PointerData():
object(0),
x(0.0f),
xMin(-1.0f),
xMax(1.0f),
y(0.0f),
yMin(-1.0f),
yMax(1.0f) {}
PointerData(osg::Object* obj, float in_x, float in_xMin, float in_xMax, float in_y, float in_yMin, float in_yMax):
object(obj),
x(in_x),
xMin(in_xMin),
xMax(in_xMax),
y(in_y),
yMin(in_yMin),
yMax(in_yMax) {}
PointerData(const PointerData& pd):
osg::Referenced(),
object(pd.object),
x(pd.x),
xMin(pd.xMin),
xMax(pd.xMax),
y(pd.y),
yMin(pd.yMin),
yMax(pd.yMax) {}
PointerData& operator = (const PointerData& pd)
{
if (&pd==this) return *this;
object = pd.object;
x = pd.x;
xMin = pd.xMin;
xMax = pd.xMax;
y = pd.y;
yMin = pd.yMin;
yMax = pd.yMax;
return *this;
}
osg::observer_ptr<osg::Object> object;
float x, xMin, xMax;
float y, yMin, yMax;
float getXnormalized() const { return (x-xMin)/(xMax-xMin)*2.0f-1.0f; }
float getYnormalized() const { return (y-yMin)/(yMax-yMin)*2.0f-1.0f; }
};
该结构体用来记录一些附加信息,这些附加信息包括:
- 产生附加信息时相关联的对象。
- 产生附加信息时相关联的位置(或起始点)及区域。
例如:在3.6.2版本的osg源码中的Viewer::eventTraversal()函数会调用Viewer::generatePointerData函数,在该函数中就有如下代码:
void Viewer::generatePointerData(osgGA::GUIEventAdapter& event)
{
....... // 其它代码略
bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
y, 0, gw->getTraits()->height));
if (camera)
{
osg::Viewport* viewport = camera->getViewport();
event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
(y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
....... // 其它代码略
}
....... // 其它代码略
}
在这里构造2个osgGA::PointerData对象,第1个对象用来记录当前鼠标点击事件的一些相关信息,比如当前点击位置,所在对象(窗口)及其尺寸,给鼠标点击事件提供更加丰富的参考信息。第2个对象用来记录相机及该相机对应的视口信息,其中第1个参数存放相机对象,并将该相机对应的视口起点位置即视口的左下角坐标归一化到[-1.0, 1.0]的区域(因为OPenGL在将场景绘制到视口时,视口范围就是[-1.0, 1.0])。
2. 各成员含义
x:产生附加信息时相关联位置的横坐标。
y:产生附加信息时相关联位置的横坐标。
xMin:产生附加信息时相关联区域最左边界即最小横坐标。
xMax:产生附加信息时相关联区域最右边界即最大横坐标。
yMin:产生附加信息时相关联区域最下边界即最小纵坐标。
yMax: 产生附加信息时相关联区域最上边界即最大纵坐标。
两个成员函数如下:
float getXnormalized() const { return (x-xMin)/(xMax-xMin)*2.0f-1.0f; }
float getYnormalized() const { return (y-yMin)/(yMax-yMin)*2.0f-1.0f; }
其功能是:产生附加信息时相关联的位置归一化到[-1.0, 1.0]的区域,因为OPenGL涉及到的区域或范围,几乎都是以[-1.0, 1.0]作为范围,不在该区域内的场景将被裁剪掉,不会被绘制。这里的算法很简单,采用等比例换算得出,如下:
左侧矩形表示实际的区域,其中(x,y)表示区域内的某个位置坐标;右侧矩形表示OPenGL标准化的 区域。则x占据左侧矩形宽度的比例为:
(x - xMin)/ (xMax - xMin)
x'占据右侧矩形宽度的比例为:
[x' - (-1.0)] / [1.0 - (-1.0)]
因为是归一化,归一化就是等比例缩放,所以上面两式应该相等,即:
(x - xMin)/ (xMax - xMin) = [x' - (-1.0)] / [1.0 - (-1.0)]
求出x'为:
(x-xMin)/(xMax-xMin)*2.0f-1.0f;
y'和x'同理。