本文共 6143 字,大约阅读时间需要 20 分钟。
本文详细介绍了工厂和海工设计软件AVEVA的交互方式,并阐述了OpenSceneGraph中的人机交互工具拖拽器的实现方法。在该框架中,我们成功实现了模型的直接交互操作。对对三维建模感兴趣的读者可以结合其源代码,对其实现细节进行深入分析。
在当代三维辅助设计软件中,交互建模设计已成为主流。友好、高效的对三维模型直接编辑或修改,不仅提高了用户的工作效率,也为用户留下了良好的用户体验。常见的交互建模方法包括拖曳、约束、栅格捕捉、橡皮筋方法和引力场方法等。如何设计高效、友好、方便的用户接口,是当前各开发系统厂家和专家共同关心的问题,其设计好坏直接影响用户是否接受产品。
本文主要介绍了AVEVA的交互建模方式,详细说明了OpenSceneGraph中拖拽器的工作原理,并在其中实现了模型的直接交互操作。通过实践,发现OpenSceneGraph的代码规范和设计非常优秀。对于对交互建模感兴趣的读者,可以结合其源代码,对实现细节进行深入分析。
AVEVA(原CADCENTRE)是国际知名的工厂工程信息技术企业,总部位于英国剑桥。AVEVA提供的工厂工程一体化解决方案涵盖多个行业,包括石油天然气、电力、化工等。其交互建模功能以Model Editor为核心,用户可以通过鼠标直接对模型进行操作,如轴向移动、平面移动、旋转和对齐等。
Model Editor的Handle允许用户对模型进行多种方式的编辑。例如,通过Linear and Planar handles进行轴向或平面移动,移动距离可通过设置移动增量来精确控制。旋转操作则通过Rotation handle完成,旋转增量可设置以确保精度。对齐功能则允许用户将模型对齐到点、边或面,提供了高效的交互体验。
OpenSceneGraph由Don Burns和Robert Osfield共同开发,是一款广泛应用于三维场景渲染的开源引擎。其核心优势包括快速开发、高品质、高性能以及开源特性。OpenSceneGraph提供了多种拖拽器,满足不同交互需求。
常见拖拽器类型包括:
通过组合模式(CompositeDragger),开发者可以将拖拽器灵活组合,例如将TranslateAxisDragger组合成三维平称拖拽器。OpenSceneGraph的开源特性使其适合定制化需求,例如与AVEVA的Model Editor类似的操作方式。
为了实现模型的拖拽操作,我们可以通过以下步骤进行:
以下是示例代码:
#pragma once#include#include #include #include class ModelShape : public osg::Group{public: ModelShape(osg::Node* shape); ~ModelShape(void); void EnableDragger(void); void DisableDragger(void); void setMatrix(const osg::Matrix& matrix); private: osg::ref_ptr mShape; osg::ref_ptr mDragger; osg::ref_ptr mSelection; };
#include "ModelShape.h"ModelShape::ModelShape(osg::Node* shape) : mShape(shape), mDragger(new TranslateAxisDragger()), mSelection(new Selection()){ float scale = shape->getBound().radius() * 1.6; mDragger->setMatrix(osg::Matrix::scale(scale, scale, scale) * osg::Matrix::translate(shape->getBound().center())); mDragger->setupDefaultGeometry(); mSelection->addChild(shape); addChild(mSelection);}ModelShape::~ModelShape(void){}void ModelShape::EnableDragger(void){ addChild(mDragger); mDragger->addTransformUpdating(mSelection); mDragger->setHandleEvents(true);}void ModelShape::DisableDragger(void){ removeChild(mDragger); mDragger->removeTransformUpdating(mSelection); mDragger->setHandleEvents(false);} #pragma once#includeclass PickHandler : public GUIEventHandler{public: PickHandler(void); ~PickHandler(void); virtual bool handle(const GUIEventAdapter& ea, GUIActionAdapter& aa); void pick(const GUIEventAdapter& ea, GUIActionAdapter& aa); private: float mX; float mY; bool mEnableDragger;};
#include "PickHandler.h"#include "ModelShape.h"PickHandler::PickHandler(void) : mX(0.0f), mY(0.0f), mEnableDragger(true){}PickHandler::~PickHandler(void){}bool PickHandler::handle(const GUIEventAdapter& ea, GUIActionAdapter& aa){ View* view = dynamic_cast (aa); if (NULL == view) { return false; } switch (ea.getEventType()) { case PUSH: { mX = ea.getX(); mY = ea.getY(); break; } case RELEASE: { if (ea.getX() == mX && ea.getY() == mY) { pick(ea, aa); } break; } case KEYDOWN: { if (ea.getKey() == 'd') { mEnableDragger = !mEnableDragger; } break; } default: break; } return false;}void PickHandler::pick(const GUIEventAdapter& ea, GUIActionAdapter& aa){ View* view = dynamic_cast (aa); LineSegmentIntersector::Intersections hits; if (view->computeIntersections(ea.getX(), ea.getY(), hits)) { LineSegmentIntersector::Intersection intersection = *hits.begin(); NodePath& nodePath = intersection.nodePath; int nNodeSize = nodePath.size(); if (nNodeSize > 0) { Node* node = nodePath[nNodeSize - 1]; Node* grandParent = node->getParent(0)->getParent(0); ModelShape* shape = dynamic_cast (grandParent); if (shape) { mEnableDragger ? shape->EnableDragger() : shape->DisableDragger(); } } }} #include#include #include using namespace std;int main(void){ Viewer viewer; RefPtr root = new Group(); for (int i = 1; i < 10; ++i) { for (int j = 1; j < 10; ++j) { RefPtr box = new MatrixTransform(); RefPtr glider = new MatrixTransform(); box->setMatrix(osg::Matrix::translate(i * 6.0, j * 6.0, 0.0)); glider->setMatrix(osg::Matrix::translate(i * 2.5, j * 2.5, 6.0)); box->addChild(new ModelShape(osgDB::readNodeFile("box.stl"))); glider->addChild(new ModelShape(osgDB::readNodeFile("glider.osg"))); root->addChild(box); root->addChild(glider); } } viewer.setSceneData(root.get()); viewer.addEventHandler(new StatsHandler()); viewer.addEventHandler(new WindowSizeHandler()); viewer.addEventHandler(new StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); viewer.addEventHandler(new PickHandler()); viewer.run(); }
通过实践,我们发现OpenSceneGraph的人机交互方式非常友好,提供了灵活的拖拽器来操纵模型。拖拽器采用组合模式设计,便于扩展和定制。OpenSceneGraph的开源特性使其适合调试和定制,同时避免了知识产权问题。
此外,OpenSceneGraph还提供了丰富的仿真效果,如烟雾、火焰、粒子效果等,这些功能可以提升建模设计的体验。如果在建模过程中适量添加这些效果,相信会让您的作品更加酷炫。
转载地址:http://nyhfk.baihongyu.com/