• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            eryar

            PipeCAD - Plant Piping Design Software.
            RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
            posts - 603, comments - 590, trackbacks - 0, articles - 0

            Implementation Model Editor of AVEVA in OpenSceneGraph

            eryar@163.com

            摘要Abstract:本文主要對工廠和海工設計軟件AVEVA的交互方式進行詳細介紹,對OpenSceneGraph中的人機交互工具拖拽器進行說明,并在其中實現(xiàn)了模型直接交互操作。對交互建模感興趣的讀者可結(jié)合其源代碼,對其實現(xiàn)細節(jié)進行分析。

            關(guān)鍵字Key Words:AVEVA, Model Editor, OpenSceneGraph, Dragger

            一、引言 Introduction

            在當代的三維輔助設計軟件中,交互建模設計已經(jīng)成為主流。友好、高效的對三維模型直接進行編輯或修改,不僅可以提高用戶的工作效率,還會給用戶留下美好印象,即軟件良好的用戶體驗。交互建模的常見方法有:拖曳、約束、柵格捕捉、橡皮筋方法、引力場等,拖曳就是直接對選擇的模型在三維空間中拖動來改變位置和方向;約束方法就是在拖曳的時候添加約束條件,如只能沿某個方向進行拖曳,軟件中的應用有AutoCAD中的極軸捕捉功能;柵格捕捉也是一種帶約束的拖曳,即拖曳的過程中只能沿正交網(wǎng)格中直線的交點拖動;橡皮筋方法主要用在繪制二維圖形;引力場方法就像AutoCAD中的磁吸功能。如何設計高效、友好、方便的用戶接口是當前各開發(fā)系統(tǒng)的廠家和專家所共同關(guān)心的問題,它的設計好壞可能直接影響用戶是否接受其產(chǎn)品。

            本文主要對工廠和海工設計軟件AVEVA的交互方式進行詳細介紹,對OpenSceneGraph中的人機交互工具拖拽器進行說明,并在其中實現(xiàn)了模型直接交互操作。通過程序?qū)嵺`,感覺使用OpenSceneGraph來進行編碼還是很舒服的,因為其代碼規(guī)范,設計很好。對交互建模感興趣的讀者可結(jié)合其源代碼,對其實現(xiàn)細節(jié)進行分析。

            二、模型編輯器Model Editor of AVEVA

            AVEVA(原CADCENTRE)是國際著名的工廠工程信息技術(shù)企業(yè),成立于1967年,總部設在英國劍橋;AVEVA所提供的工廠工程一體化解決方案涵蓋了陸地和海洋石油天然氣、電力、石化、化工、核電、造船、環(huán)保、造紙、制藥、冶金、礦山等多個行業(yè),同時提供專業(yè)工廠工程技術(shù)咨詢、技術(shù)服務和本地化可持續(xù)發(fā)展的應用開發(fā)。 AVEVA是目前全球發(fā)展最快的工廠工程信息技術(shù)企業(yè)之一,1996年在英國倫敦上市,2007財年年產(chǎn)值超過25億美元。AVEVA在全球擁有超過1600名用戶,每天有超過26,000名工程人員在使用AVEVA的解決方案。AVEVA在世界30多個國家和地區(qū)設有超過50個常駐辦事機構(gòu),在英國劍橋總部及其他研發(fā)中心擁有超過300名研究和開發(fā)人員,為世界上最大的工廠工程信息技術(shù)研究和開發(fā)團隊。AVEVA的快速發(fā)展與其方便易用,良好的交互建模方式分不開,本文主要對其交互建模部分進行介紹。

            AVEVA交互建模主要是使用模型編輯器Model Editor,使用Model Editor可以只用鼠標就可以進行建模設計了。編輯選擇的模型如下圖所示:

            wps_clip_image-19277

            Figure 2.1 Model Editor on a Equipment

            使用的Handle可以對模型多種方式的編輯,如軸向移動、平面移動、旋轉(zhuǎn)等,如下圖所示:

            wps_clip_image-19280

            Figure 2.2 Locator Handle of Model Editor

            2.1 移動 Movement

            對選擇的模型進行軸向移動或平面移動時,可以使用Model Editor的Linear and Planar handles。沿軸向或鎖定在某個平面上拖動模型,即可以移動模型。移動是按一定的長度遞增的,可由移動增量(the Movement Increment)來設置,這樣來確保拖動模型相對初始位置的精度。選中handle上某個軸,就可以沿這個軸的方向來移動模型,如下圖所示:

            wps_clip_image-3474

            Figure 2.3 Linear Movement

            選中并拖動Model Editor的平面移動handle,就可以在鎖定的平面上移動模型,如下圖所示:

            wps_clip_image-107

            Figure 2.4 Planar Movement

            2.2 旋轉(zhuǎn) Rotation

            旋轉(zhuǎn)是通過Model Editor的Rotation handle來完成的。旋轉(zhuǎn)是按一定的角度來遞增的,可由旋轉(zhuǎn)增量(the Rotation Increment)來設置。這樣就確保了旋轉(zhuǎn)相對于初始位置的精度。選中并拖動Rotation handle,就可以對模型進行旋轉(zhuǎn)了,如下圖所示:

            wps_clip_image-693

            Figure 2.5 Rotation

            wps_clip_image-5192 wps_clip_image-23407

            Figure 2.6 Use Model Editor to Modify a Valve

            交互建模時使用Model Editor如上圖2.6所示,由圖可知,在AVEVA中對模型的移動和旋轉(zhuǎn)非常方便。

            2.3 對齊 Alignment

            通過對齊功能,可以方便地將模型對齊到點、邊或面,如下圖所示:

            wps_clip_image-710

            Figure 2.7 Alignment features

            通過上文對AVEVA中的Model Editor的介紹可知,在AVEVA中三維交互建模很方便,且精度高。縱觀國內(nèi)目前類似產(chǎn)品,有些還停留在二維建模方式,有些借助于其他平臺的交互方法,但是在易用性上感覺都稍有不足,或沒有自主的知識產(chǎn)權(quán)。

            三、拖拽器Dragger of OpenSceneGraph

            1997年,一個名叫Don Burns的軟件工程師受雇于當時的Silicon Graphics(SGI)公司,負責針對滑翔機飛行的虛擬仿真工作進行研究。他使用當時的OpenGL Performer系統(tǒng),設計了一套廣受好評的滑翔仿真軟件,并開始嘗試在Linux中使用Mesa3D和3dfx Voodoo顯卡設備繼續(xù)完善自己的仿真軟件。

            1998年,Don在一個滑翔愛好者的郵件組中遇到了Robert Osfield,也就是目前OpenSceneGraph項目的主要負責人。當時Robert在蘇格蘭的油氣公司工作,但對計算機圖形學和可視化技術(shù)有著濃厚的興趣。志趣相投的兩個人走到了一起,開始合作對Don的仿真軟件進行改善。Robert建議將SG作為獨立的開源場景圖形項目繼續(xù)開發(fā),并由自己擔任項目主導,項目的名稱改為OpenSceneGraph,簡稱OSG。

            如今,相當一部分高性能的軟件已經(jīng)使用了OSG來完成復雜場景的渲染工作。大部分基于OSG的軟件開發(fā)更適用于可視化設計和工業(yè)仿真,包括地理信息系統(tǒng)(GIS)、計算機輔助設計(CAD)、建模和數(shù)字媒體創(chuàng)作(DCC)及數(shù)據(jù)庫開發(fā)、虛擬現(xiàn)實、動畫、游戲和娛樂業(yè)等。

            OpenSceneGraph引擎由一系列圖形學相關(guān)的功能模塊組成,主要為圖形圖像應用程序的開發(fā)提供場景管理和圖形渲染優(yōu)化的功能。它使用可移植的ANSI C++編寫,并使用已成為工業(yè)標準的OpenGL底層渲染API。OSG具備跨平臺的特性,可以運行在大多數(shù)類型的操作系統(tǒng)上,并使用抽象層的概念,使OSG的函數(shù)接口可以獨立于用戶的本地操作系統(tǒng)使用。OSG遵循開源協(xié)議發(fā)布,其用戶許可方式是一種修改過的GNU寬通用公共許可證(GNU Lesser General Public License, LGPL),稱為OSGPL。OSG主要具備以下優(yōu)勢:快速開發(fā),高品質(zhì),高性能,高質(zhì)量代碼,可擴展性,可移植性,低費用,沒有知識產(chǎn)權(quán)問題,但是OSG目前也存在諸多不足,如參考文檔較少、代碼風格不統(tǒng)一、部分功能的實現(xiàn)過于臃腫,無法應用于實踐等,這些都有待更多的開發(fā)者和貢獻者去發(fā)現(xiàn)和完善。

            三維用戶交互是一種與三維環(huán)境本身特性相匹配的交互動作,可使用戶在虛擬場景中獲得身臨其境的直觀感受。三維世界的交互技術(shù)相當于一種“控制-顯示”的映射,用戶設備(例如鼠標、鍵盤、操縱桿等)向系統(tǒng)輸入控制信息,然后系統(tǒng)向用戶輸出執(zhí)行結(jié)果。三維交互涉及的任務繁多,包括三維場景對象的選擇和操控、三維世界中的導航漫游、改變?nèi)S場景的狀態(tài),乃至時下流行的三維交互建模等。作為一款全面的實時渲染引擎,OSG實現(xiàn)了三維場景的漫游及場景中三維對象的操控這兩種主要的三維場景交互方式,更多的交互動作則需要我們自行研究和實現(xiàn)。

            作為重要的三維空間的人機交互手段之一,場景漫游的特點是通過不斷改變觀察者(相機)的位置、姿態(tài),使其相對世界的觀察方位和角度有所變化,但是世界本身卻不會發(fā)生任何改變。無論草木、建筑,還是街道上的車水馬龍,構(gòu)成它們的每一個頂點都沒有發(fā)生任何偏移,如果觀察者有朝一日回到原地的話,他眼中的一切都不會發(fā)生改變。

            而對于三維物體的操控則是另一種概念,它沒有改變觀察者的視角和視點,而是根據(jù)用戶傳遞的交互事件,對選中的對象進行平移、縮放和旋轉(zhuǎn)操作,就像是玩弄橡皮泥一樣。被修整過的對象將改變原有的形態(tài),換句話說,只要不恢復到操控前的狀態(tài),那么無論從什么地方進行觀察,這個對象都將維持它最終的模樣。當然,即使操控物體的定義如此,直接修改物體的頂點坐標未免還是有些費力不討好,最好的方式是為要操控的物體設置一個矩陣變換的父節(jié)點(MatrixTransform),通過改變這個父節(jié)點的變換矩陣的值,進行改變作為操控對象的子節(jié)點的表現(xiàn)形式—這就是osgManipulator庫中拖拽器(Dragger)的實現(xiàn)方式。OSG內(nèi)置了幾種拖拽器,其操作方式和效果說明如下:

            l TabPlaneDragger平面拖拽器:其邊、頂點上都有拖拽點,可以進行某個2D平面上的縮放;

            wps_clip_image-1294

            Figure 3.1 TabPlaneDragger in OpenSceneGraph

            l TabPlaneTrackballDragger平面軌跡球拖拽器:顧名思義除了平面拖拽器的功能外,還多了個軌跡球拖拽功能;

            wps_clip_image-2369

            Figure 3.2 TabPlaneTrackballDragger in OpenSceneGraph

            l TrackballDragger軌跡球拖拽器:即旋轉(zhuǎn)操縱器,沒有縮放功能;

            wps_clip_image-16308

            Figure 3.3 TrackballDragger in OpenSceneGraph

            l Translate1DDragger一維平移拖拽器:沿一個直線進行拖拽;

            wps_clip_image-26274

            Figure 3.4 Translate1DDragger in OpenSceneGraph

            l Translate2DDragger二維平移拖拽器:在某個平面上對模型進行拖拽;

            wps_clip_image-6327

            Figure 3.5 Translate2DDragger in OpenSceneGraph

            l TranslateAxisDragger三維平移拖拽器:可在三個方向上對模型進行拖拽;

            wps_clip_image-15562

            Figure 3.6 TranslateAxisDragger in OpenSceneGraph

            l TabBoxDragger盒式拖拽器:由六個平面拖拽器構(gòu)成,可在各個面上進行縮放、平移;

            wps_clip_image-21705

            Figure 3.7 TabBoxDragger in OpenSceneGraph

            還有其他的拖拽器可以參考其源代碼:

            n ScaleAxisDragger:三維縮放拖拽器;

            n Scale2DDragger:二維縮放拖拽器;

            n Scale1DDragger一維縮放拖拽器;

            n RotateSphereDragger:旋轉(zhuǎn)球拖拽器;

            n RotateCylinderDragger旋轉(zhuǎn)圓柱拖拽器;

            由于使用了組合模式(CompositeDragger),可將上面的拖拽器組合成更復雜的拖拽器。如三維平稱拖拽器(TranslateAxisDragger)就是包含了三個一維拖拽器(Translate1DDragger)的組合拖拽器。因為程序開源,所以可根據(jù)實際需要,將拖拽器進行自定義。即可以定義出和AVEVA的Model Editor完全一樣的操縱器。

            四、示例程序 Example Code

            要對場景中的模型進行拖拽,首先需要將其選中,然后在選中的模型上打開拖拽器,對模型的位置和方向進行編輯。對象的拾取主要依靠場景圖形的交運算來實現(xiàn)。拖拽器中用到的一個類PointerInfo表示一個信息的集合。例如,使用鼠標選中待操作對象上的某個點,以及當前相機的觀察矩陣和投影矩陣等,都需要及時反映到這個輸入?yún)?shù)中,以便拖拽器根據(jù)實際情況進行判斷并生成命令。下面給出一個使用拖拽器Dragger來操作場景中模型的具體實例,程序代碼如下所示:

            1.首先定義了一個帶拖拽器的節(jié)點ModelShape:

             

            #pragma once

            #include 
            <osg/Group>

            #include 
            <osgManipulator/Selection>
            #include 
            <osgManipulator/CommandManager>
            #include 
            <osgManipulator/TrackballDragger>
            #include 
            <osgManipulator/TranslateAxisDragger>


            class ModelShape : public osg::Group
            {
            public:
                ModelShape(osg::Node
            * shape);
                
            ~ModelShape(void);

                
            void EnableDragger(void);
                
            void DisableDragger(void);

            private:
                osg::ref_ptr
            <osg::Node> mShape;
                osg::ref_ptr
            <osgManipulator::Dragger> mDragger;
                osg::ref_ptr
            <osgManipulator::Selection> mSelection;
            };

            類實現(xiàn)代碼如下所示:

             

            #include "ModelShape.h"

            ModelShape::ModelShape(osg::Node
            * shape)
            : mShape(shape)
            , mDragger(
            new osgManipulator::TranslateAxisDragger())
            , mSelection(
            new osgManipulator::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()
            {
                addChild(mDragger);

                mDragger
            ->addTransformUpdating(mSelection);
                mDragger
            ->setHandleEvents(true);
            }


            void ModelShape::DisableDragger()
            {
                removeChild(mDragger);

                mDragger
            ->removeTransformUpdating(mSelection);
                mDragger
            ->setHandleEvents(false);
            }

            2.在處理選擇事件時,打開拖拽器,實現(xiàn)類是PickHandler:

             

            #pragma once

            #include 
            <osgGA/GUIEventHandler>


            class PickHandler : public osgGA::GUIEventHandler
            {
            public:
                PickHandler(
            void);
                
            ~PickHandler(void);

                
            virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);

            protected:
                
            void pick(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);

            private:
                
            float mX;
                
            float mY;
                
            bool mEnableDragger;
            };

            類實現(xiàn)代碼如下所示:

             


            #include 
            "PickHandler.h"
            #include 
            "ModelShape.h"

            #include 
            <osgViewer/Viewer>


            PickHandler::PickHandler(
            void)
            : mX(
            0.0f)
            , mY(
            0.0f)
            , mEnableDragger(
            true)
            {

            }


            PickHandler::
            ~PickHandler(void)
            {
            }


            bool PickHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
            {
                osgViewer::View
            * view = dynamic_cast<osgViewer::View*> (&aa);
                
            if (NULL == view)
                {
                    
            return false;
                }

                
            switch (ea.getEventType())
                {
                
            case osgGA::GUIEventAdapter::PUSH:
                    {
                        mX 
            = ea.getX();
                        mY 
            = ea.getY();
                    }
                    
            break;

                
            case osgGA::GUIEventAdapter::RELEASE:
                    {
                        
            if (ea.getX() == mX && ea.getY() == mY)
                        {
                            pick(ea, aa);
                        }
                    }
                    
            break;

                
            case osgGA::GUIEventAdapter::KEYDOWN:
                    {
                        
            if (ea.getKey() == 'd')
                        {
                            mEnableDragger 
            = !mEnableDragger;
                        }
                    }
                    
            break;

                
            default:
                    
            break;
                }

                
            return false;
            }


            void PickHandler::pick(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
            {
                osgViewer::View
            * view = dynamic_cast<osgViewer::View*> (&aa); 

                osgUtil::LineSegmentIntersector::Intersections hits;
                
            if (view->computeIntersections(ea.getX(), ea.getY(), hits))
                {
                    osgUtil::LineSegmentIntersector::Intersection intersection 
            = *hits.begin();
                    osg::NodePath
            & nodePath = intersection.nodePath;
                    
            int nNodeSize = static_cast<int> (nodePath.size());

                    
            if (nNodeSize > 0)
                    {
                        osg::Node
            * node = nodePath[nNodeSize - 1];
                        osg::Node
            * grandParent = node->getParent(0)->getParent(0);

                        
            // This method maybe not right?
                        ModelShape* shape = dynamic_cast<ModelShape*> (grandParent);
                        
            if (shape)
                        {
                            mEnableDragger 
            ? shape->EnableDragger() : shape->DisableDragger();
                        }

                    }
                }

            }

            3.在主函數(shù)中建立場景:

             

            /*
            *    Copyright (c) 2013 eryar All Rights Reserved.
            *
            *           File : Main.cpp
            *         Author : eryar@163.com
            *           Date : 2013-12-28 17:00
            *        Version : 1.0v
            *
            *    Description : Use dragger to manipulate shape objects.
            *                  press key 'd' for enable or disable the dragger.
            *
            *      Key Words : OpenSceneGraph, Dragger
            *                  
            */

            #include 
            <osgDB/ReadFile>
            #include 
            <osgGA/StateSetManipulator>

            #include 
            <osgViewer/Viewer>
            #include 
            <osgViewer/ViewerEventHandlers>


            #include 
            "ModelShape.h"
            #include 
            "PickHandler.h"


            #pragma comment(lib, 
            "osgd.lib")
            #pragma comment(lib, 
            "osgDBd.lib")
            #pragma comment(lib, 
            "osgGAd.lib")
            #pragma comment(lib, 
            "osgViewerd.lib")
            #pragma comment(lib, 
            "osgManipulatord.lib")


            int main(void)
            {
                osgViewer::Viewer viewer;

                osg::ref_ptr
            <osg::Group> root = new osg::Group();

                
            // build the scene with boxes and gliders.
                for (int i = 1; i < 10++i)
                {
                    
            for (int j = 1; j < 10++j)
                    {
                        osg::ref_ptr
            <osg::MatrixTransform> box = new osg::MatrixTransform();
                        osg::ref_ptr
            <osg::MatrixTransform> glider = new osg::MatrixTransform();

                        box
            ->setMatrix(osg::Matrix::translate(i * 6.0, j * 6.00.0));
                        glider
            ->setMatrix(osg::Matrix::translate(i * 2.5, j * 2.56.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 osgViewer::StatsHandler());
                viewer.addEventHandler(
            new osgViewer::WindowSizeHandler());
                viewer.addEventHandler(
            new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

                
            // add pick event handler to add dragger on the shape.
                viewer.addEventHandler(new PickHandler());

                
            return viewer.run();
            }

            程序使用方法為選擇要拖拽的模型,選中后為模型打開拖拽器,使用拖拽器對模型進行拖拽就可以修改模型的位置了。在鍵盤上按下‘d’可以打開/關(guān)閉拖拽器,默認為打開。當設置為關(guān)閉時,再選中帶有拖拽器的模型后,將會關(guān)閉拖拽器。程序運行效果如下圖所示:

            wps_clip_image-9879

            Figure 3.8  Use TranslateAxisDragger to drag box

            wps_clip_image-12412

            Figure 3.9 Use TranslateAxisDragger to drag glider

            wps_clip_image-28372

            Figure 3.10 Use TranslateAxisDragger in OpenSceneGraph

            五、結(jié)論 Conclusion

            通過程序?qū)嵺`表明,OpenSceneGraph中的人機交互的方式還是很方便的,并提供了幾種拖拽器來操縱模型。并且拖拽器采用了組合模式,便于擴展,即根據(jù)用戶實際需要組合出更復雜或更具個性的拖拽器。

            由此可見,使用OpenSceneGraph來對模型進行顯示與操作很方便,且是開源程序,方便程序調(diào)試,還不存在知識產(chǎn)權(quán)的問題。因為OpenSceneGraph主要是用于虛擬仿真,還提供了很多仿真效果,如煙霧、火焰、粒子效果(雨、雪、爆炸)、動畫等,如果在建模設計的過程中適量添加部分效果,是不是很cool?

            六、參考資料 References

            1. AVEVA,Graphical Model Manipulation Guide

            2. Donald Hearn,M. Pauline Baker,Computer Graphics with OpenGL,電子工業(yè)出版社

            3. 何援軍,計算機圖形學,機械工業(yè)出版社

            4. 王銳,錢學雷,OpenSceneGraph三維渲染引擎設計與實踐,清華大學出版社

            5. 肖鵬,劉更代,徐明亮,OpenSceneGraph三維渲染引擎編程指南,清華大學出版社

             

            中文字幕人妻色偷偷久久| 久久激情亚洲精品无码?V| 国内精品久久久久久不卡影院| 九九久久自然熟的香蕉图片| 人妻无码αv中文字幕久久| 99久久精品国产高清一区二区 | 久久亚洲欧美日本精品| 99久久国产综合精品成人影院| 久久996热精品xxxx| 99久久免费只有精品国产| 久久久精品免费国产四虎| 人人狠狠综合久久亚洲88| 久久综合欧美成人| 久久久久国产精品三级网| 久久久久无码精品| 区久久AAA片69亚洲| segui久久国产精品| 人妻精品久久无码专区精东影业| 久久人人爽人人爽人人片AV东京热| 99久久国产综合精品女同图片| 久久99这里只有精品国产| 久久久久久曰本AV免费免费| 久久久免费精品re6| 亚洲伊人久久综合中文成人网| 久久99热只有频精品8| 久久亚洲综合色一区二区三区| 久久99精品国产麻豆蜜芽| 久久无码人妻精品一区二区三区| 精品999久久久久久中文字幕| 久久精品视频一| 久久久久久亚洲精品无码| 一本色道久久88综合日韩精品 | 久久久精品一区二区三区| 国产精自产拍久久久久久蜜| 精品久久久久久无码不卡| 91精品国产9l久久久久| 亚洲第一永久AV网站久久精品男人的天堂AV| 精品久久久久久中文字幕| 亚洲国产成人久久综合一区77| 人妻精品久久久久中文字幕69 | 一级做a爰片久久毛片16|