使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容

作者:Jorge Canton Ferrero
排版:Alan Wang

这是来自 Plain Concepts 的 Jorge Canton 的客座博客文章。Jorge 是技术初创公司 Syderis 的联合创始人,12 年来一直致力于计算机图形、游戏引擎和图形工具领域的开发。目前,他担任 Plain Concepts 的研究总监,积极参与 Evergine 的开发,Evergine 是一款专为行业应用量身定制的尖端 3D 图形引擎。

使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第1张图片
您在使用电子商务平台的时候,曾产生过希望能够使用 3D 图像而不是静态图像展示并从任何角度查看产品的想法吗?您曾经在查看大型购物中心的地图的时候,是否有过如果可以用可探索的 3D 地图,导航会更容易的念头?在本文中,我们将学习如何使用 .NET MAUI 实现所有这些以及更多的功能。

什么是 Evergine?

Evergine 是一款于 2012 年用 C# 开发的跨平台 3D 引擎。Evergine 因无缝集成功能而闻名并成为工业项目的首选。它可以轻松地集成到现有项目中,也可以与其他技术配合使用。借助 Evergine,您可以制作与各种平台兼容的应用程序,包括 Windows、Linux、Android、iOS、Hololens、Meta Quest/Quest2/Quest Pro、Pico 和 Web。

Evergine 还拥有与各种 UI 技术的无缝集成,包括 WPF、Forms、SDL、UWP、Html/Javascript、WinUI,现在甚至还包括 .NET MAUI。我们致力于跟踪最新的 .NET 版本和工具,为我们的客户提供最佳的体验。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第2张图片
Evergine 的主要功能包括:
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第3张图片
Evergine 的使用是完全免费的,没有许可费和版税,适用于商业和非商业项目。Evergine 的商业模式是围绕其提供的附加服务进行收费,例如:

  • 优先支持——我们提供 72 小时 SLA 为您在项目中使用 Evergine 时可能遇到的任何问题提供帮助和技术支持。
  • 源代码访问——我们授予您访问 Evergine 源代码的全部权限。
  • 专业服务——您可以根据您的需求参加培训课程、一对一课程、概念验证和新功能。

价格可在官方网站上查询。

Evergine 如何与 .NET .NET MAUI 一起使用

在最新的 Evergine 版本中,引入了新的 .NET MAUI 项目模板。有了这个模板,Evergine 可以让您创建一个标准的 .NET MAUI 项目,其中包含 EvergineView 控件,该控件可以无缝集成到应用程序的任何视图中。EvergineView 控件充当 Evergine 生成的 3D 场景的画布,您可以使用 Evergine Studio 配置它。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第4张图片
EvergineView 是一个抽象的自定义 .NET MAUI 控件,使您能够跨 Windows、Android 和 iOS 平台无缝工作。

public class EvergineView : View
 {
     public static readonly BindableProperty ApplicationProperty =
         BindableProperty.Create(nameof(Application), typeof(EvergineApplication), typeof(EvergineView), null);

     public static readonly BindableProperty DisplayNameProperty =
         BindableProperty.Create(nameof(DisplayName), typeof(string), typeof(EvergineView), string.Empty);

     public EvergineApplication Application
     {
         get { return (EvergineApplication)this.GetValue(ApplicationProperty); }
         set { this.SetValue(ApplicationProperty, value); }
     }

     public string DisplayName
     {
         get { return (string)this.GetValue(DisplayNameProperty); }
         set { this.SetValue(DisplayNameProperty, value); }
     }

     public event EventHandler PointerPressed;

     public event EventHandler PointerMoved;

     public event EventHandler PointerReleased;

     internal void StartInteraction() => this.PointerPressed?.Invoke(this, EventArgs.Empty);

     internal void MovedInteraction() => this.PointerMoved?.Invoke(this, EventArgs.Empty);

     internal void EndInteraction() => this.PointerReleased?.Invoke(this, EventArgs.Empty);
 }

另一方面,渲染实现是使用每个平台的自定义处理程序创建的。以下代码是 Android 处理程序的示例。

public partial class EvergineViewHandler : ViewHandler<EvergineView, AndroidSurfaceView>
  {
      private AndroidSurface androidSurface;
      private AndroidWindowsSystem windowsSystem;

      public EvergineViewHandler(IPropertyMapper mapper, CommandMapper commandMapper = null)
         : base(mapper, commandMapper)
      { }

      public static void MapApplication(EvergineViewHandler handler, EvergineView evergineView)
      {
          handler.UpdateApplication(evergineView, evergineView.DisplayName);
      }

      internal void UpdateApplication(EvergineView view, string displayName)
      {
          if (view.Application is null) { return; }

          // Register Windows system
          view.Application.Container.RegisterInstance(this.windowsSystem);

          // Creates XAudio device
          var xaudio = new global::Evergine.OpenAL.ALAudioDevice();
          view.Application.Container.RegisterInstance(xaudio);

          System.Diagnostics.Stopwatch clockTimer = System.Diagnostics.Stopwatch.StartNew();
          this.windowsSystem.Run(
          () =>
          {
              this.ConfigureGraphicsContext(view.Application as SneakerApp.MyApplication, this.androidSurface);
              view.Application.Initialize();
          },
          () =>
          {
              var gameTime = clockTimer.Elapsed;
              clockTimer.Restart();

              view.Application.UpdateFrame(gameTime);
              view.Application.DrawFrame(gameTime);
          });
      }

      protected override AndroidSurfaceView CreatePlatformView()
      {
          this.windowsSystem = new AndroidWindowsSystem(this.Context);
          this.androidSurface = this.windowsSystem.CreateSurface(0, 0) as AndroidSurface;
          return this.androidSurface.NativeSurface;
      }

      private void ConfigureGraphicsContext(MyApplication application, Surface surface)
      {
          var graphicsContext = new VKGraphicsContext();
          graphicsContext.CreateDevice();
          SwapChainDescription swapChainDescription = new SwapChainDescription()
          {
              SurfaceInfo = surface.SurfaceInfo,
              Width = surface.Width,
              Height = surface.Height,
              ColorTargetFormat = PixelFormat.R8G8B8A8_UNorm,
              ColorTargetFlags = TextureFlags.RenderTarget | TextureFlags.ShaderResource,
              DepthStencilTargetFormat = PixelFormat.D24_UNorm_S8_UInt,
              DepthStencilTargetFlags = TextureFlags.DepthStencil,
              SampleCount = TextureSampleCount.None,
              IsWindowed = true,
              RefreshRate = 60,
          };
          var swapChain = graphicsContext.CreateSwapChain(swapChainDescription);
          swapChain.VerticalSync = true;

          var graphicsPresenter = application.Container.Resolve<GraphicsPresenter>();
          var firstDisplay = new global::Evergine.Framework.Graphics.Display(surface, swapChain);
          graphicsPresenter.AddDisplay("DefaultDisplay", firstDisplay);

          application.Container.RegisterInstance(graphicsContext);

          surface.OnScreenSizeChanged += (_, args) =>
          {
              swapChain.ResizeSwapChain(args.Height, args.Width);
          };
      }
  }

此外,Evergine 自定义处理程序的注册是在项目的 MauiProgram.cs 文件中执行的。

public static class .NET MAUIProgram
    {
        public static .NET MAUIApp CreateMauiApp()
        {
            var builder = .NET MAUIApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .UseMauiEvergine()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if DEBUG
        builder.Logging.AddDebug();
#endif

            return builder.Build();
        }
    }

最后,3D 场景可能非常复杂,可能包含各种资源,例如纹理、材质和模型等。Evergine 可以方便地将所有 3D 场景资源打包并传输到设备上。为了实现这一目标,Evergine 模板包含了特定的目标,将 3D 内容标记为 MauiAsset ,并将其注入到 .NET MAUI 目标管道中。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第5张图片

入门指南

从官方网站下载并安装 Evergine 后,您首先要了解 Evergine 启动器。它使您能够管理不同的版本、使用各种项目模板创建新项目、访问示例项目以及查找支持和文档的链接。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第6张图片
如果您想要从 Evergine 启动器启动新项目,请导航至“My Projects”部分,然后单击“Add New Project”按钮
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第7张图片
此时项目配置窗口就会打开,允许您选择项目名称、项目的磁盘位置以及所需的 Evergine 版本。此外,您还可以选择新的 .NET MAUI 模板。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第8张图片
单击“Create”按钮后,Evergine Studio 就会打开。然后,您可以将任何基本对象添加到场景中,并附加一个 Spinner 组件,其值为{x:1, y:2, z:3},以实现对基本对象的旋转。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第9张图片
如果您想要访问 .NET MAUI 解决方案,只需从 Evergine Studio 中的“File”菜单将其打开即可。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第10张图片
当您在 Visual Studio 中启动 .NET MAUI 解决方案时,您会发现该解决方案中有两个集成项目。第一个项目是您在所有模板之间共享的 Evergine 项目,第二个是 .NET MAUI 项目,它引用了 Evergine 项目。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第11张图片
在 .NET MAUI 项目中,您将会找到 Platform 文件夹,其中包含特定于平台的资源,例如 Android Manifest 和 Info.plist 文件。在 Evergine 文件夹中,您将看到 EvergineView 控件。该控件可以轻松集成到您的 XAML 页面中,使您能够包含 Evergine 画布来渲染 3D 场景。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第12张图片
如果您想要在各种平台上部署您的项目,请使用 Visual Studio 中的“Run/Deploy”按钮。请注意,对于 iOS 部署,您需要在 Visual Studio 和 Mac 之间建立连接,并将 iOS 设备(iPad 或 iPhone)链接到您的 Mac。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第13张图片
在 .NET MAUI 解决方案中成功部署项目后,您将获得类似于上述示例的结果。下图展示了 .NET MAUI 中的基本 XAML 页面,其中包含一个 Label 和一个 EvergineView。这只是一个示例,但您可以自由地利用最新的 .NET 技术和 Evergine 来制作出色的项目。
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第14张图片
您可以探索我们的展示应用程序,它演示了如何将移动应用程序 UI 与 3D 内容无缝融合,并有效地在 Evergine 和 .NET MAUI UI 之间进行通信。

EverSneaks 展示应用程序

存储库:https://github.com/EvergineTeam/EverSneaks
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第15张图片

CarRental展示应用程序(作者:@Javier Suarez)

存储库:https://github.com/jsuarezruiz/netmaui-carrental-app-challenge
使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容_第16张图片

Evergine 主要资源

在 Evergine 官方网站中,您可以找到很多有关入门 Evergine 的有趣资源,以下是最重要的资源。

  • Evergine 文档
  • 示例工程存储库
  • 视频教程
  • Youtube 频道
  • 反馈
  • 联系方式

展望未来

目前 .NET MAUI 模板使用 .NET 7稳定版。在11 月份 .NET 8 稳定版发布后,为了使用最新的改进和功能,我们会将 .NET MAUI 模板更新为 .NET 8 稳定版。

我们坚信社区可以利用这些技术打造出极具吸引力的应用程序。我们迫不及待地想要见证您将 3D 与 .NET MAUI 相结合,从而创造出令人激动的作品的过程!

我们非常期待您的反馈。祝您在使用 Evergine 和 .NET MAUI 编码时愉快!

你可能感兴趣的:(.net,3d,c#)