当前位置: 首页 > news >正文

沈阳网站关键词优化做的好吗今日军事头条

沈阳网站关键词优化做的好吗,今日军事头条,济南香港国际网站建设,北京网站开发公司大全目录 1. 需求的提出 2. 具体实现 2.1. 禁止场景跟随鼠标转动 2.2. 矩形框前置绘制 3. 附加说明 3.1. 颜色设置说明 3.2.矩形框显示和隐藏的另一种实现 1. 需求的提出 有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键,拖出一个矩形,实现框…

目录

1. 需求的提出

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

     2.2. 矩形框前置绘制

3. 附加说明

        3.1. 颜色设置说明

        3.2.矩形框显示和隐藏的另一种实现


1. 需求的提出

       有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键,拖出一个矩形,实现框选三维物体,如下效果:

现在的问题是:

  1. 在osg中,拖动鼠标时,物体会随鼠标一起转动,这样框选是不行的,至少是不友好的,我们需要的是,按住鼠标框选时,物体不能随鼠标一起转动。
  2. 如何根据鼠标拖动的起始点和终止点,绘制出这个矩形框?矩形框要在所有三维物体的前面而不能被三维物体遮挡且要是透明的,能透过它看到背后的三维物体,否则框选就失去了意义。
  3. 按住鼠标右键,矩形框消失。

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

        对第1节中提到的第1个问题,默认情况下osgViewer::Viewer事件处理器在鼠标左键按下并拖动时,整个场景会随鼠标一起转动。为了不让转动,可以通过改写osgViewer::Viewer osgGA::GUIEventHandler事件处理器,重载如下方法:

 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv)

当按住键盘上的某个键如Ctrl键且按住鼠标左键,让该函数返回true,这样后续的流程就不会处理鼠标拖动事件,三维物体也就不会跟随鼠标旋转了。

     2.2. 矩形框前置绘制

         矩形框要绘制在所有三维物体的前面而不能被三维物体遮挡,这就要用到三维中的HUD技术(Head Up Display)。所谓HUD节点,说白了就是无论三维场景中的内容怎么改变,它都能在屏幕上固定位置显示的节点。实现要点:

  • 关闭光照,不受场景光照影响,所有内容以同一亮度显示。
  • 关闭深度测试。
  • 调整渲染顺序,使它的内容最后绘制。
  • 设定参考贴为绝对型:setReferenceFrame(osg::Transform:ABSOLUTE_RF)。
  • 使其不受父节点变换的影响:setMatrix(osg::Matrix::identity())。
  • 使用平行投影,设定虚拟投影窗口的大小,这个窗口的大小决定了后面绘制的图形和文字的尺度比例。

  实现代码如下:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>
class selectBoxEventHandler: public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HUD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey()) || (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被释放{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();auto pSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}m_spHudCamera->addChild(pSelectBox);m_spOldNode = pSelectBox;return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{0.0};float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{false};             // Ctrl键被按下bool m_bPush{false};                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{nullptr};osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Node> m_spOldNode;      // 上次鼠标框选绘制出的矩形框};
int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 关闭深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

3. 附加说明

        3.1. 颜色设置说明

              2.2节代码对颜色的设置,也可以按如下代码一样达到同样的效果:

 osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pQuardGeomerty->setColorArray(pColorArray);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);

也就是说设置一个顶点的颜色且颜色绑定方式为BIND_PER_PRIMITIVE_SET和分别设置4个顶点颜色,颜色绑定方式为BIND_PER_VERTEX效果相同。关于BIND_PER_PRIMITIVE_SET和BIND_PER_VERTEX的具体含义和不同点,请参考:osg图元绑定方式总结博文。

        3.2.矩形框显示和隐藏的另一种实现

       上面矩形框的显示和隐藏是通过removeChild和addChild函数来实现的,即将新的矩形框节点加入到相机作为其子节点之前,删除上次创建的矩形框节点。也可以通过osg::Node的setNodeMask函数来实现,如下为更改后的代码:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>#define HIDE_SELECT_BOX 0X0
#define  SHOW_SELECT_BOX ~HIDE_SELECT_BOXclass selectBoxEventHandler : public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HuD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spRectGeometry != nullptr){m_spRectGeometry->setNodeMask(HIDE_SELECT_BOX);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();if (nullptr != m_spRectGeometry){auto pVertArray = (osg::Vec3Array*)m_spRectGeometry->getVertexArray();(*pVertArray)[0].set(m_fStartPosX, m_fStartPosY, 0.0);(*pVertArray)[1].set(m_fStartPosX, m_fEndPosY, 0.0);(*pVertArray)[2].set(m_fEndPosX, m_fEndPosY, 0.0);(*pVertArray)[3].set(m_fEndPosX, m_fStartPosY, 0.0);// m_spRectGeometry->setVertexArray(pVertArray);m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形m_spRectGeometry->setNodeMask(SHOW_SELECT_BOX);}else{auto spSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);m_spRectGeometry = spSelectBox->asGeode()->getChild(0)->asGeometry();m_spHudCamera->addChild(spSelectBox);}return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{ 0.0 };float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{ false };             // Ctrl键被按下bool m_bPush{ false };                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{ nullptr };osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Geometry> m_spRectGeometry;      // 矩形框};int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 开启深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

说明

  • 在鼠标拖动坐标改变重新设置矩形框坐标时,记得调用:           
// 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形 
m_spRectGeometry->setVertexArray(pVertArray);

或调用:

 m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形

在C++中,只要把指针指向的内容改了,也就是立马改了,但在上述代码中如果以为只把顶点数据改了,新矩形就会呈现出来是错误的,不调用上述代码中的某一种,新矩形不会绘制,因为只改了顶点数据,但osg还没执行重绘。

  • 上述采用节点的setNodeMask函数,通过设置节点掩码来实现矩形框的显示或隐藏,其实最好的方法是采用osg::Switch来控制矩形框的显示和隐藏,在此不再详述列出代码,关于这两者的详述,参见:osg利用setNodeMask和Switch隐藏节点用法说明博文。
http://www.ds6.com.cn/news/55564.html

相关文章:

  • 免费的网站软件正能量免费推广有哪些
  • 品牌网站建设内容框架免费拓客软件排行榜
  • 坪山网站建设服务镇江网站建设方案
  • 定制型网站建设合同范本域名注册信息怎么查
  • 常州网页搜索排名提升宁波网站seo公司
  • 网站建设公司违法seo综合查询是什么意思
  • 外贸网站 在线留言百度搜索竞价
  • 做动态网站用哪个程序软件比较简单?微营销平台系统
  • 新密做网站优化三亚网络推广
  • 做网站的为什么一直拖360搜索指数
  • 电子商务网站有那些功能广州番禺发布网
  • 网站建设公司怎么运营推广软件赚钱的app
  • 百度推广网页制作seo导航
  • 阜阳城乡建设局网站免费seo刷排名
  • 嘉兴市建设教育网站百度软文
  • wordpress整站下载免费建站工具
  • 东莞建网站市场营销策划ppt
  • 安徽合肥建设局网站站长工具站长之家
  • 橙 网站常见的营销型网站
  • 最好看免费观看高清大全八百电影百度地图优化
  • 建设专业网站怎样收费百度软件下载
  • 杭州网站设计建设公司郑州seo公司哪家好
  • 自己设计的网站如何推广windows优化大师下载
  • 石家庄做网站最好的公司哪家好网站seo诊断技巧
  • 企业网站如何设置关键词专业seo网络营销公司
  • 山东广饶县建设局网站怎么在平台上做推广
  • 谷歌云做网站泰安seo
  • 外贸建站的公司万网官网
  • 怎么给网站命名seo网站优化推广费用
  • 网站开发的操作可行性衡阳seo外包