查看: 2772|回复: 25

如何pick到HUDcamera中的节点,新人求助

[复制链接]

该用户从未签到

发表于 2013-5-14 22:23:45 | 显示全部楼层 |阅读模式
我现在想pick到HUDcamera中的节点,然后对其做相应的操作,但总也实现不了,能帮帮我吗?

该用户从未签到

发表于 2013-5-15 07:51:25 | 显示全部楼层
pick是没问题的  哪里实现不了?

该用户从未签到

 楼主| 发表于 2013-5-15 09:18:38 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 07:51
pick是没问题的  哪里实现不了?

大概过程是这样的

该用户从未签到

 楼主| 发表于 2013-5-15 09:26:44 | 显示全部楼层
huxing613 发表于 2013-5-15 09:18
大概过程是这样的

osg::ref_ptr<osg::Camera>camera = new osg::Camera;
camera->addchild(node.get());
camera->setname("name1");
node->setname("name2");
root->addchild(camera.get());
程序运行后,在屏幕上能够显示相机窗口,还有里边的node,但当我用鼠标点击按名称去pick这个相机窗口时,发现它就像透明的一样,怎么也找不到,有什么好的办法和思路吗,求明示。

该用户从未签到

发表于 2013-5-15 09:48:00 | 显示全部楼层
关键的pick 没有一点信息

该用户从未签到

 楼主| 发表于 2013-5-15 09:55:49 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 09:48
关键的pick 没有一点信息

不好意思,这个是我的pick程序,您看一下

该用户从未签到

 楼主| 发表于 2013-5-15 09:55:50 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 09:48
关键的pick 没有一点信息

不好意思,这个是我的pick程序,您看一下

该用户从未签到

 楼主| 发表于 2013-5-15 09:55:50 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 09:48
关键的pick 没有一点信息

不好意思,这个是我的pick程序,您看一下

该用户从未签到

 楼主| 发表于 2013-5-15 10:04:09 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 09:48
关键的pick 没有一点信息

void CMyEventCallback::pick(float x,float y)
{        
      osg::Node* node;        
      osgUtil:ineSegmentIntersector::Intersections::iterator hitr;   
     osgUtil::LineSegmentIntersector::Intersections intersections;  
     if (!viewer) return;                                            
     if(viewer->computeIntersections(x,y,intersections));   
     for(hitr = intersections.begin();hitr !=intersections.end();++hitr)        
          {                
               if (!hitr->nodePath.empty()&&!hitr->nodePath.back()->getName().empty())                
               {                        
                osg::NodePath np = hitr ->nodePath;                        
                osg::Matrix mat = osg::computeLocalToWorld(np);                        
                for (int i=np.size()-1; i>=0; --i)                        
                 {                                
                      node = np;                                
                      std::string nodename = node->getName();                                 
                      if (nodename == LCU_CABINET_NAME)   
                            相应操作                               
                      if (nodename==DOOR_NAME)   
                            相应操作                               
                 }
           }
}

问题就是这个函数,总是找不到焦点if(viewer->computeIntersections(x,y,intersections));   

该用户从未签到

发表于 2013-5-15 12:05:09 | 显示全部楼层
检查x/y的值是否正确,viewer->computeIntersections(x,y,intersections) 这样使用是没问题的 hud中的东西也可以pick到

该用户从未签到

 楼主| 发表于 2013-5-15 18:31:24 | 显示全部楼层
liuzhiyu123 发表于 2013-5-15 12:05
检查x/y的值是否正确,viewer->computeIntersections(x,y,intersections) 这样使用是没问题的 hud中的东西也 ...

谢谢您的回复,那我再检查一下x,y的取值。

该用户从未签到

发表于 2013-5-16 00:10:54 | 显示全部楼层
估计是你的pick在主摄像机关联的窗口,而新建的你摄像机只是能反应和显示Viewer下地东东(如同照相截图),但他没有关联到当前的Viewer!
  你的PICK实际是在主摄像机的对应了场景PICK, 视点确在另一个摄像机下。

该用户从未签到

 楼主| 发表于 2013-5-16 09:55:44 | 显示全部楼层
本帖最后由 huxing613 于 2013-5-16 09:56 编辑
VR_user_happy 发表于 2013-5-16 00:10
估计是你的pick在主摄像机关联的窗口,而新建的你摄像机只是能反应和显示Viewer下地东东(如同照相截图), ...


确实是这样的,我的pick关联在viewer的主相机,而新建的相机只是addchild到root下,那如何将它关联到viewer呢?用addslave吗?

该用户从未签到

发表于 2013-5-16 10:43:49 | 显示全部楼层
为什么要ADD到ROOT 下?
viewer关联摄像机,可以用setCamera();
也可用addslave(),单效果有差别,自己试试吧

该用户从未签到

发表于 2013-5-16 12:54:05 | 显示全部楼层
HUDcamera 当然要加到Root下面,HUD中pick是可以的 不知道您的设置 哪里有问题

该用户从未签到

发表于 2013-5-16 14:31:34 | 显示全部楼层
好像没有HUDcamera这个类呀

该用户从未签到

发表于 2013-5-16 15:09:45 | 显示全部楼层
明白了,你是要设个新相机显示HUD下的东西
首先要清楚你的HUD大小,这个大小决定了这个区域的里面只会是2D显示;
   你的pick鼠标移动到这个区域,PICK 能起作用吗,深度测试都取消了,PICK 能起什么作用

该用户从未签到

发表于 2013-5-16 15:10:58 | 显示全部楼层
给你个参考
int main()
{
osg::Group* root = new osg::Group();        // 初始化根节点
osg:ositionAttitudeTransform* tankXform;
osg::Geode* HUDGeode = new osg::Geode();       // HUD 几何体的叶节点

osgText::Text* textOne = new osgText::Text();      // 用于作HUD 显示的Text 实例
osgText::Text* tankLabel = new osgText::Text();      // 这个文字实例将跟随坦克显示
// 读入模型并关联到节点
osg::Node* tankNode = osgDB::readNodeFile("t72-tank_des.flt"); // 坦克节点
osg::Node* terrainNode = osgDB::readNodeFile("JoeDirt.flt"); // 地形节点

// 初始化位置变换节点,用于放置坦克模型
tankXform = new osg::PositionAttitudeTransform();
tankXform->setPosition(osg::Vec3d(5, 5, 8));

// 构件场景。将地形节点和位置变换节点关联到根节点
root->addChild(terrainNode);
root->addChild(tankXform);
tankXform->addChild(tankNode);

// 下一步,设置场景显示HUD 文字。这里我们向场景中添加一个子树,其顶层节点使用投影和模型观察矩阵。
// 将投影矩阵添加到根节点。投影矩阵的水平和垂直范围与屏幕的尺寸相同。因此该节点子树中的位置坐标将等同于像素坐标
osg::Projection* HUDProjectionMatrix = new osg::Projection; // 投影节点用于定义HUD 的视景体
HUDProjectionMatrix->setMatrix(osg::Matrix:rtho2D(0, 1024, 0, 768));

// HUD 模型观察矩阵应使用单位矩阵
osg::MatrixTransform* HUDModelViewMatrix = new osg::MatrixTransform;
HUDModelViewMatrix->setMatrix(osg::Matrix::identity());

// 确保模型观察矩阵不会被场景图形的位置变换影响
HUDModelViewMatrix->setReferenceFrame(osg::Transform::ABSOLUTE_RF);

// 添加HUD 投影矩阵到根节点,添加HUD 模型观察矩阵到HUD投影矩阵。
// 模型观察矩阵节点的所有子节点都可以使用该投影矩阵进行视景
// 浏览,并使用模型观察矩阵来安置位置
root->addChild(HUDProjectionMatrix);
HUDProjectionMatrix->addChild(HUDModelViewMatrix);

// 现在我们设置几何体。我们创建一个与屏幕坐标对齐的四边形,并设置其颜色和纹理参数。
// 将包含 HUD 几何体的Geode 节点作为HUD 模型观察矩阵的子节点
HUDModelViewMatrix->addChild(HUDGeode);

// 设置HUD 的四边形背景,并添加到Geode 节点
osg::Geometry* HUDBackgroundGeometry = new osg::Geometry();
osg::Vec3Array* HUDBackgroundVertices = new osg::Vec3Array;
HUDBackgroundVertices->push_back(osg::Vec3(0,    0,   -1));
HUDBackgroundVertices->push_back(osg::Vec3(1024, 0,   -1));
HUDBackgroundVertices->push_back(osg::Vec3(1024, 200, -1));
HUDBackgroundVertices->push_back(osg::Vec3(0,    200, -1));
osg:rawElementsUInt* HUDBackgroundIndices = new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0);
HUDBackgroundIndices->push_back(0);
HUDBackgroundIndices->push_back(1);
HUDBackgroundIndices->push_back(2);
HUDBackgroundIndices->push_back(3);
osg::Vec4Array* HUDcolors = new osg::Vec4Array;
HUDcolors->push_back(osg::Vec4(0.1f, 0.2f, 0.4f, 0.8f));
osg::Vec2Array* texcoords = new osg::Vec2Array(4);
(*texcoords)[0].set(0.0f, 0.0f);
(*texcoords)[1].set(1.0f, 0.0f);
(*texcoords)[2].set(1.0f, 1.0f);
(*texcoords)[3].set(0.0f, 1.0f);
HUDBackgroundGeometry->setTexCoordArray(0, texcoords);
osg::Texture2D* HUDTexture = new osg::Texture2D;
HUDTexture->setDataVariance(osg::Object::DYNAMIC);
osg::Image* hudImage;
hudImage = osgDB::readImageFile("hudbk.jpg");
HUDTexture->setImage(hudImage);
osg::Vec3Array* HUDnormals = new osg::Vec3Array;
HUDnormals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
HUDBackgroundGeometry->setNormalArray(HUDnormals);
HUDBackgroundGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
HUDBackgroundGeometry->addPrimitiveSet(HUDBackgroundIndices);
HUDBackgroundGeometry->setVertexArray(HUDBackgroundVertices);
HUDBackgroundGeometry->setColorArray(HUDcolors);
HUDBackgroundGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
HUDGeode->addDrawable(HUDBackgroundGeometry);

// 我们需要创建一个osg::StateSet,并禁止深度测试(总是在屏幕上绘制),允许Alpha 混合
// (使HUD 背景透明),以保证HUD 的渲染正确。然后我们使用一个指定数字的渲染元来分配
// 几何体在拣选遍历中的渲染顺序。代码如下所示:
// 设置渲染状态,使用上面定义的纹理
osg::StateSet* HUDStateSet = new osg::StateSet();
HUDGeode->setStateSet(HUDStateSet);
HUDStateSet->setTextureAttributeAndModes(0,HUDTexture,osg::StateAttribute::ON);

//打开GL_BLEND 混合模式(以保证Alpha 纹理正确)
HUDStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);

// 禁止深度测试,因此几何体将忽略已绘制物体的深度值,直接进行绘制
HUDStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
HUDStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
// 确认该几何题在最后进行绘制。渲染元(RenderBin)按照数字顺序执行渲染,因此我们设置一个较大的数字值
HUDStateSet->setRenderBinDetails(11, "RenderBin");

// 最后我们设置文字。由于osg::Text 继承自osg::Drawable,其实例可以作为osg::Geode实例的子节点添加到场景中。
// 添加文字到 Geode 叶节点中
HUDGeode->addDrawable(textOne);

// 设置HUD 文字的参数
textOne->setCharacterSize(25);
textOne->setFont("/fonts/YGY2.ttf");
textOne->setText(L"孤舟钓客:泛舟四海,笑傲江湖!");
textOne->setAxisAlignment(osgText::Text::SCREEN);
textOne->setPosition(osg::Vec3(360, 165, -1.5));
textOne->setColor(osg::Vec4(199, 77, 15, 1));

// 声明一个叶节点来保存坦克的标签文字
osg::Geode* tankLabelGeode = new osg::Geode();

// 将坦克标签添加到场景中
tankLabelGeode->addDrawable(tankLabel);
tankXform->addChild(tankLabelGeode);

// 设置坦克标签文字的参数,与坦克的坐标对齐,
// 这里使用XZ_PLANE 保证文字与坦克的XZ 平面对齐
tankLabel->setCharacterSize(5);
tankLabel->setFont("/fonts/YGY2.ttf");
tankLabel->setText(L"Tank 1号");
tankLabel->setAxisAlignment(osgText::Text::XZ_PLANE);

// 设置文字渲染时包括一个对齐点和包围矩形
tankLabel->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT | osgText::Text::BOUNDINGBOX);
tankLabel->setAlignment(osgText::Text::CENTER_TOP);
tankLabel->setPosition(osg::Vec3(0, 0, 8));
tankLabel->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));

// 最后,设置视景类并进入仿真循环。
osgViewer::Viewer viewer;
viewer.setSceneData(root);
return viewer.run();
}?

该用户从未签到

发表于 2013-5-16 15:32:01 | 显示全部楼层
VR_user_happy 发表于 2013-5-16 15:09
明白了,你是要设个新相机显示HUD下的东西
首先要清楚你的HUD大小,这个大小决定了这个区域的里面只会是2D ...

您在说什么?osg中的相交测试 跟 深度测试有关系么?  什么叫只会显示2D的东西?

该用户从未签到

发表于 2013-5-16 17:23:44 | 显示全部楼层
本帖最后由 VR_user_happy 于 2013-5-16 17:25 编辑

creating an HUD camera
A head-up display (HUD) can render data without requiring users to look away from their usual viewpoints. It is widely used in 3D scenes, for displaying important 2D texts, computer game statistics, and flight and cockpit instruments. This time, we are going to design an HUD camera, which contains a model that should be placed in front of other scene objects at any time.
1.        1. Include the necessary headers:
2.        #include <osg/Camera>
3.        #include <osgDB/ReadFile>
4.        #include <osgViewer/Viewer>
5.        2. Two models are loaded from disk files. lz.osg is used as a demo terrain, and glider.osg will be put under an HUD camera. That is, it will always be visible to viewers who are looking ahead; no matter how other parts of the scene graph are changing:
6.        osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("lz.osg");
7.        osg::ref_ptr<osg::Node> hud_model = osgDB::readNodeFile("glider.osg");
8.        3. The HUD camera and its children must be rendered after the regular scene is finished being drawn on the screen. It will overwrite all present pixel data, regardless of its location and depth. That is why we use GL_DEPTH_BUFFER_BIT to clear the depth buffer. The GL_COLOR_BUFFER_BIT is not set here, to ensure that the color buffer is correctly reserved.
9.        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
10.        camera->setClearMask( GL_DEPTH_BUFFER_BIT );
11.        camera->setRenderOrder( osg::Camera:OST_RENDER );
12.        4. The HUD camera should not be affected by the viewer or any other parent nodes, so it needs to be changed to the absolute reference frame, and be set as a custom fixed view matrix. The glider is also added to the camera node, used as the content to be displayed:
13.        camera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
14.        camera->setViewMatrixAsLookAt(
15.        osg::Vec3(0.0f,-5.0f,5.0f), osg::Vec3(), osg::Vec3(0.0f,1.0f,1.0f)
16.        );
17.        camera->addChild( hud_model.get() );
18.        5. We will add the HUD camera, along with a regular loaded model, to the root node:
19.        osg::ref_ptr<osg::Group> root = new osg::Group;
20.        root->addChild( model.get() );
21.        root->addCh XE "render-to-textures technique:ild( camera.get() );
22.        6. Now, start the viewer as usual:
23.        osgViewer::Viewer viewer;
24.        viewer.setSceneData( root.get() );
25.        return viewer.run();
26.        7. You will see that the demo terrain (regular scene) is rendered and manipulated under the user's control. However, the glider (post-rendered scene) always stays on top of all other scene objects, and its position and orientation will never be affected by the mouse or keyboard inputs.

该用户从未签到

发表于 2013-5-16 17:59:06 | 显示全部楼层
To render the HUD, we'll assign the geometry in it to a specific RenderBin. RenderBins allow users to specify the order in which geometry is drawn. This is helpful since the HUD geometry needs to be drawn last.

该用户从未签到

发表于 2013-5-24 13:11:54 | 显示全部楼层
本帖最后由 VR_user_happy 于 2013-5-24 13:13 编辑

看了OSGPICK的例子,它是用
osgUtil:: PickVisitor iv;
和osgUtil:: IntersectVisitor
或者用osgUtil:: PolytopeIntersector::Intersection intersection =
picker->getFirstIntersection();
实现对HUD的节点拾取!
可以参考:osgpick.cpp
osgUtil::IntersectVisitor:: HitList& hlist=iv.getHits(scene, vum, x,y);
97                std::string gdlist="";
98                if (iv.hits())
99                {
100                    for(osgUtil:: IntersectVisitor:: HitList:: iterator hitr=hlist.begin();
101                    hitr!=hlist.end();
102                    ++hitr)
103                    {
104                        //osg::Vec3 ip = hitr->getLocalIntersectPoint();
105                        //osg::Vec3 in = hitr->getLocalIntersectNormal();
106                        osg::Geode* geode = hitr->_geode.get();
107                        // the geodes are identified by name.
108                        if (geode) {
109                            gdlist=gdlist+" "+geode->getName();
110                        }
111                    }
112                }

该用户从未签到

发表于 2013-5-24 13:24:38 | 显示全部楼层
呵呵,您的这个osgPick  应该是很古老的了

该用户从未签到

发表于 2013-5-24 14:07:09 | 显示全部楼层
本帖最后由 VR_user_happy 于 2013-5-24 14:18 编辑

其实:HUD节点下NODE的位置信息并没有丢失
只是camera设置了绝对帧osg::Camera::ABSOLUTE_RF,而使得它的位置在渲染时不再受影响,就如同按下了快门,照了一张相(而不是连续摄影),做了频幕投影。

所以,上面英文中划线部分我认为可能需要(作者)对这一点需要更正,不是忽略了它的LOCATION!

实际上:
它是利用了摄像机的两个参数
ABSOLUTE_RF
GL_DEPTH_BUFFER_BIT
实现-->节点最后渲染到频幕的一种技巧!

该用户从未签到

发表于 2013-5-24 14:08:59 | 显示全部楼层
顶楼上

该用户从未签到

发表于 2013-5-24 14:10:09 | 显示全部楼层
pick是osg的事件处理 hudcamera可以当作是ui的处理 看你的挂载的是什么ui库了 不管什么库相应的操作基本都差不多
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表