OSG(OpenSceneGraph)的.NET封装1-快速创建基于osgEarth.NET和Fluent.Ribbon的数字地球程序

1.使用VS2019新建WPF窗体程序

NuGet添加Fluent.Ribbon程序包。

NuGet添加Tx.osgEarth程序包。

2.app修改


        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/Fluent;Component/Themes/Generic.xaml" />
                <ResourceDictionary Source="pack://application:,,,/Fluent;component/Themes/Themes/Dark.Blue.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>

3.修改MainWindow

修改基类为RibbonWindow,添加Ribbon、OsgearthView和StatusBar控件。

<Fluent:RibbonWindow  xmlns:Fluent="urn:fluent-ribbon" x:Class="OsgEarthExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:OsgEarthExample"
        xmlns:wfi="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
        xmlns:toeui="clr-namespace:Tx.osgEarth.UI;assembly=Tx.osgEarth"
                      mc:Ignorable="d"
        Title="腾雪osgEarth演示" Height="450" Width="800" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="311*"/>
            <ColumnDefinition Width="489*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <!--Ribbon-->
            <RowDefinition Height="Auto"></RowDefinition>
            <!--工作窗口-->
            <RowDefinition></RowDefinition>
            <!--StatusBar-->
            <RowDefinition Height="25"></RowDefinition>
        </Grid.RowDefinitions>
        <!--Ribbon-->
        <Fluent:Ribbon Name ="ribbon" Grid.ColumnSpan="2" VerticalAlignment="Center">
            <!--Tabs-->
            <!--TFluent:RibbonTabItem Header="地球">
                <Fluent:RibbonGroupBox Header="视图" IsLauncherVisible="False">
                    <Fluent:Button Header="飞往" />
                </Fluent:RibbonGroupBox>
            </Fluent:RibbonTabItem-->
        </Fluent:Ribbon>
        <!--工作窗口-->
        <wfi:WindowsFormsHost  Grid.Row="1" Grid.ColumnSpan="2" Margin="0,0,0,25" Grid.RowSpan="2">
            <toeui:OsgEarthCtrl x:Name="osgEarthView" Dock="Fill"/>
        </wfi:WindowsFormsHost>
        <!--StatusBar-->
        <Fluent:StatusBar Grid.Row="2" Grid.ColumnSpan="2">
            <Fluent:StatusBarItem Title="Ready"
                          Value="150"
                          HorizontalAlignment="Left">
                <TextBlock x:Name="tbInfo" Text="就绪" />
            </Fluent:StatusBarItem>

            <Separator HorizontalAlignment="Left" />

            <Fluent:StatusBarItem Title="WebSite"
                          HorizontalAlignment="Right"
                          Value="www.tengxuekeji.com " />
        </Fluent:StatusBar>
    </Grid>
</Fluent:RibbonWindow>

到此可以直接运行程序,显示osgEarth窗口了。

4.引入腾雪科技的App插件框架

MianWindow完成接口

public partial class MainWindow : RibbonWindow, IMainWindow, IViewWindow
 #region IWindow

        /// <summary>Window句柄.</summary>
        /// <value>The handle.</value>
        public IntPtr Handle  => ((HwndSource)PresentationSource.FromDependencyObject(this)).Handle;

        /// <summary>图标.</summary>
        /// <value>The icon.</value>
        public object IconImage
        {
            get
            {
                return this.Icon;
            }
            set
            {
                this.Icon = value as ImageSource;
            }
        }

        #endregion

        #region IMainWindow


        /// <summary>Gets the active view window.</summary>
        /// <value>The active view window.</value>
        public object ActiveViewWindow => this;

        /// <summary>更新UI.</summary>
        public void RefreshUI()
        {
            this.InvalidateVisual();
        }

        /// <summary>Occurs when [view window active].</summary>
        public event Action<IViewWindow> ViewWindowActive;

        #endregion

        #region IViewWindow
        /// <summary>
        /// Gets the parent.
        /// </summary>
        /// <value>The parent.</value>
        public object ParentWindow => this.Owner;

        /// <summary>
        /// Gets the view.
        /// </summary>
        /// <value>The view.</value>
        public object View => osgEarthView;

        #endregion

添加成员

 public AppService AppService { get; private set; }

在构造函数完成初始化

        public MainWindow()
        {
            Instance = this;
            InitAppService();

            InitializeComponent();

            var osgEarthObj = this.osgEarthView.OsgEarthObj;

            var map = osgEarthObj.MapNode.Map;
            map.addLayer(new TileSourceImageLayer() { TileSource = new WebTileSource(MapTileType.TIANDITU_IMG), Name = nameof(MapTileType.TIANDITU_IMG) });
            map.addLayer(new TileSourceImageLayer() { TileSource = new WebTileSource(MapTileType.TIANDITU_CIA), Name = nameof(MapTileType.TIANDITU_CIA) });

            InitRibbon();

            ViewWindowActive?.Invoke(this);
        }

        private void InitRibbon()
        {
            var ribbonLoader = new RibbonLoader(ribbon, AppService);
            ribbonLoader.Tab("地球").Group("视图")
                .AddBotton<FlyToCmd>("飞往", null, null);
            ribbonLoader.Tab("地球").Group("图层")
                .AddBotton<HideOrShowTiandituCiaCmd>("天地图矢量", null, null);
        }

        private void InitAppService()
        {
            AppService = new AppService() { MainWindow = this };
            // 绑定预定义的消息
            AppService.Singleton<MessageProxy>().OnShow =
                delegate(string s, string s1, MsgBoxButtons arg3, MsgBoxIcon arg4)
                {
                    var result = TxDialogResult.Cancel;
                    this.SafeInvoke(() =>
                    {
                        result = (TxDialogResult)MessageBox.Show(this, s, s1, (MessageBoxButton)arg3,
                            (MessageBoxImage)arg4);
                    });
                    return result;
                };
            AppService.Singleton<MessageProxy>().OnShowAlert += delegate(string text, string caption)
            {
                this.SafeInvoke(() => { MessageBox.Show(this, text, caption); });
            };
            AppService.Singleton<ProgressProxy>().OnSetText += caption =>
            {
                this.SafeInvoke(() =>
                {
                    bool bRefresh = false;
                    if (caption != null && tbInfo.Text != caption)
                    {
                        tbInfo.Text = caption;
                        bRefresh = true;
                    }

                    //                     if (bRefresh)
                    //                     {
                    //                         Application.DoEvents();
                    //                     }
                });
            };
            AppService.Singleton<ProgressProxy>().OnSetValue += value =>
            {
                this.SafeInvoke(() =>
                {
                    //                     bool bRefresh = false;
                    //                     if (value > 0 && tsProgressBar.Value != value)
                    //                     {
                    TaskbarManager.Instance.SetProgressValue(value, 100, this.Handle);
                    // 
                    //                         tsProgressBar.Value = value;
                    //                         bRefresh = true;
                    //                     }
                    // 
                    //                     if (bRefresh)
                    //                     {
                    //                         statusStrip.Refresh();
                    //                         Application.DoEvents();
                    //                     }
                });
            };
            AppService.Singleton<ProgressProxy>().OnClear += () =>
            {
                this.SafeInvoke(() =>
                {
                    TaskbarManager.Instance.SetProgressValue(0, 100, this.Handle);

                    tbInfo.Text = "就绪";
                    //tsProgressBar.Value = 0;
                    //statusStrip.Refresh();
                    //Application.DoEvents();
                });
            };
        }

运行效果

 

实例程序地址 北京腾雪科技有限责任公司/OsgExample (gitee.com)

转载请标明作者和出处,有问题请回复或发邮件
作者:田腾
QQ:tian_teng@qq.com
QQ群:469468407

### 回答1: osgOpenSceneGraph)是一个性能强大的3D图形开发工具包,它提供了丰富的图形特效和功能,可以帮助开发者快速搭建高质量的3D应用程序。 要入门osg,我们可以先通过下载CSDN提供的相关教程和例子来学习。CSDN是一个面向中国IT技术人员的在线社区平台,提供了丰富的技术资源和工具。 在CSDN的下载页面中,我们可以找到osg入门教程的相关材料和代码,其中包括osg基本概念、osg渲染管线的实现、场景图的构建、纹理贴图等方面的内容。 另外,CSDN还提供了大量的osg例子,这些例子涵盖了从简单到复杂的各种场景,包括模型载入、场景组织、动画、光照、阴影、粒子效果等等。 通过下载这些材料和例子,我们可以了解osg的基本原理和应用,快速入门并掌握osg的使用方法。同时,CSDN这样的在线社区也可以提供技术支持和交流平台,使我们更好地掌握osg的技术和发挥创造力。 ### 回答2: osgOpenSceneGraph)是一种高性能图形引擎,可用于开发各种类型的图形应用程序,例如游戏、虚拟现实和科学可视化。本文将介绍osg的基础知识,方便初学者快速入门。 首先,你需要下载osg的安装包。在CSDN网站搜索osg入门,然后选择相应的安装包进行下载和安装。安装完成后,可以使用osgviewer命令行工具来预览osg模型。例如,输入以下命令: osgviewer cow.osg 这将显示一个名为“cow.osg”的osg模型。 osg还提供了一些可用于创建和定制osg模型的库和工具。其中包括osgDB(读写osg模型文件)、osgGA(处理用户输入事件)和osgUtil(提供常用的osg工具功能)。在学习osg时,建议先学习这些库和工具的基础知识。 此外,还可以使用osgEarth库来创建地图和地球表面应用程序osgEarth提供了各种地形图、影像和矢量图层,可以轻松创建具备真实感的虚拟地球体验。同样,在学习osg时,建议先学习osgEarth的基础知识。 osg的其他高级特性包括shader编程、后处理效果、场景图优化和跨平台支持等。掌握这些高级特性需要更多的经验和实践。 总之,osg是一种功能强大的图形引擎,它的入门门槛很低,但它也提供了许多高级特性,满足更高级别的应用需求。希望这篇文章能够帮助你入门osg,以便在osg应用开发中取得更好的成果。 ### 回答3: osg是一个优秀的图形渲染引擎,由于其在地形渲染、光照、场景管理等方面表现优异,被广泛应用于游戏、仿真等领域。如果对osg感兴趣,建议首先了解其基础概念和使用方法,并掌握osg的开发环境。在学习osg前,需要了解C++语言和OpenGL编程基础,并懂得如何使用开发工具比如Cmake、Visual Studio等集成开发环境。在此基础上,可以在下载CSDN的osg相关资料,如osg手册、示例代码、视频教程等内容进行入门学习,结合实践掌握osg的常用技术和开发经验。同时,建议参考一些经验丰富的osg开发者的博客和社区,如OSG中国论坛等,了解osg最新的发展和应用情况,促进自己的学习和成长。总之,osg是一个优秀的图形渲染引擎,适合于热爱计算机图形学和游戏开发的技术人员,通过不断学习和实践,可以在osg技术方面迈出更大的步伐。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值