{"id":48457,"date":"2023-10-20T10:05:00","date_gmt":"2023-10-20T17:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=48457"},"modified":"2024-01-22T16:38:01","modified_gmt":"2024-01-23T00:38:01","slug":"dotnet-maui-3d-app-with-evergine","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-maui-3d-app-with-evergine\/","title":{"rendered":"Building 3D Applications and Content with .NET MAUI and Evergine"},"content":{"rendered":"<blockquote>\n<p>This is a guest blog post by <strong>Jorge Canton<\/strong> from Plain Concepts. Jorge co-founded the technology start-up Syderis and dedicated over 12 years to specializing in computer graphics, game engines, and graphics tools. Currently, he holds the position of Research Director at <a href=\"https:\/\/www.plainconcepts.com\/\" \/>Plain Concepts<\/a>, where he is actively involved in the development of <a href=\"https:\/\/evergine.com\/\/\" \/>Evergine<\/a>, a cutting-edge 3D graphics engine tailored for industry applications.<\/p>\n<\/blockquote>\n<p>Have you ever used an e-commerce platform and wished you could visualize products from any angle using a 3D representation instead of static images? Have you ever looked at a map of a large shopping mall and thought it would be much easier to navigate if you could explore a 3D map? In this article, we will learn how to achieve all of this and more using .NET .NET MAUI.<\/p>\n<p><iframe width=\"800\" height=\"450\" src=\"https:\/\/www.youtube.com\/embed\/vWAXrP69QX4?si=6GqQ1ZnPmwLt6u-u\" allowfullscreen><\/iframe><\/p>\n<h2>What is Evergine?<\/h2>\n<p>Evergine is a cross-platform 3D engine developed in C# back in 2012. Evergine is renowned for its seamless integration capabilities, making it a top choice for industrial projects. It can easily be incorporated into existing projects or paired with other technologies. With Evergine, you can craft applications compatible with a wide range of platforms, including Windows, Linux, Android, iOS, Hololens, Meta Quest\/Quest2\/Quest Pro, Pico, and Web.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/header.jpg\" alt=\"Header\" \/><\/p>\n<p>Evergine also boasts seamless integration with various UI technologies, including WPF, Forms, SDL, UWP, Html\/Javascript, WinUI, and now, even .NET MAUI. We are committed to staying up to date with the latest .NET versions and tooling to provide our customers with the best possible experience.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/evergine-architecture.jpg\" alt=\"Evergine architecture\" \/><\/p>\n<p>The key features of Evergine include:<\/p>\n<p>td, th {\n   border: none!important;\n}<\/p>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature1.jpg\" alt=\"Advanced PBR rendering\" \/><\/td>\n<td><strong>Advanced PBR rendering<\/strong>  <br \/>Bring your application to a new level of realism using Physically based rendering and materials.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature2.jpg\" alt=\"Component based graphics engine\" \/><\/td>\n<td><strong>Component based graphics engine<\/strong> <br \/>Evergine is a Component based Engine. This allows us to reduce the complexibility and overall development cost of your applications.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature3.jpg\" alt=\"Customizable RenderPipeline and RenderPath\" \/><\/td>\n<td><strong>Customizable RenderPipeline and RenderPath<\/strong> <br \/>Customize the way that Evergine render your applications to adapt to new scenarios.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature4.jpg\" alt=\"Physics Engine simulations\" \/><\/td>\n<td><strong>Physics Engine simulations<\/strong> <br \/>Simulate a wide range of physics behaviors, collisions, and joints, both in 3D and 2D.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature5.jpg\" alt=\"Advanced Post-Processing pipeline\" \/><\/td>\n<td><strong>Advanced Post-Processing pipeline<\/strong> <br \/> Increase the realism of your application using post-Proccessing effects like Tone Mapping, SSR, SSAO, TAA, and much more!<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature6.jpg\" alt=\"Photometric Lighting and Cameras\" \/><\/td>\n<td><strong>Photometric Lighting and Cameras<\/strong> <br \/> Use real lightning units and setup your virtual camera using advanced exposure parameters.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature7.jpg\" alt=\"Modern graphics API support\" \/><\/td>\n<td><strong>Modern graphics API support<\/strong> <br \/>Increase the performance of your applications thanks to next generation graphics APIs: DirectX12, Vulkan and Metal. Apart from this, Evergine supports DirectX11, OpenGL (ES) and WebGL.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature8.jpg\" alt=\"Modern GPU Particles\" \/><\/td>\n<td><strong>Modern GPU Particles<\/strong> <br \/>3D and 2D particles can be used to enhance the visuals of your app, creating a wide range of effects.<\/td>\n<\/tr>\n<tr>\n<td><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/feature9.jpg\" alt=\"Advanced Animation System\" \/><\/td>\n<td><strong>Advanced Animation System<\/strong> <br \/>The animation system extracts the object, skeleton and morphing animations of your 3d models, easing the blending between them. Lot of options are offered, like synchronized blending and multiple tracks at the same time.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Evergine is entirely <strong>free to use, with no licensing fees or royalties<\/strong>, making it suitable for both commercial and non-commercial projects. Evergine&#8217;s business model revolves around providing additional services such as:<\/p>\n<ul>\n<li><a href=\"https:\/\/evergine.com\/priority-support\/\">Priority Support<\/a>\nWe provide assistance and technical support for any questions or problems you may have using Evergine on your projects with a 72h SLA.<\/li>\n<li><a href=\"https:\/\/evergine.com\/source-code\/\">Source Code Access<\/a>\nWe grant you total access to the source code of Evergine.<\/li>\n<li><a href=\"mailto:info@evergine.com\">Professional Services<\/a>\nYou will have access to training sessions, one-to-one sessions, proof of concepts and new features according to your needs.<\/li>\n<\/ul>\n<p>Prices are available on the <a href=\"https:\/\/evergine.com\/\">official web site<\/a><\/p>\n<h2>How Evergine works with .NET .NET MAUI<\/h2>\n<p>In the latest Evergine release, a new .NET MAUI project template has been introduced. With this template, Evergine enables you to create a standard .NET MAUI project that incorporates an EvergineView control, which can be seamlessly integrated into any view of your application. This EvergineView serves as a canvas for a 3D scene generated by Evergine, allowing you to configure it using Evergine Studio.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/evergine_view.jpg\" alt=\"Evergine view\" \/><\/p>\n<p>The EvergineView is an abstract custom .NET MAUI control that enables you to work seamlessly across Windows, Android, and iOS platforms.<\/p>\n<pre><code class=\"language-csharp\"> public class EvergineView : View\n {\n     public static readonly BindableProperty ApplicationProperty =\n         BindableProperty.Create(nameof(Application), typeof(EvergineApplication), typeof(EvergineView), null);\n\n     public static readonly BindableProperty DisplayNameProperty =\n         BindableProperty.Create(nameof(DisplayName), typeof(string), typeof(EvergineView), string.Empty);\n\n     public EvergineApplication Application\n     {\n         get { return (EvergineApplication)this.GetValue(ApplicationProperty); }\n         set { this.SetValue(ApplicationProperty, value); }\n     }\n\n     public string DisplayName\n     {\n         get { return (string)this.GetValue(DisplayNameProperty); }\n         set { this.SetValue(DisplayNameProperty, value); }\n     }\n\n     public event EventHandler PointerPressed;\n\n     public event EventHandler PointerMoved;\n\n     public event EventHandler PointerReleased;\n\n     internal void StartInteraction() =&gt; this.PointerPressed?.Invoke(this, EventArgs.Empty);\n\n     internal void MovedInteraction() =&gt; this.PointerMoved?.Invoke(this, EventArgs.Empty);\n\n     internal void EndInteraction() =&gt; this.PointerReleased?.Invoke(this, EventArgs.Empty);\n }<\/code><\/pre>\n<p>On the flip side, the rendering implementation was created using a <a href=\"https:\/\/learn.microsoft.com\/dotnet\/maui\/user-interface\/handlers\/\">custom handler<\/a> for each platform. The following code serves as an example of the Android handler.<\/p>\n<pre><code class=\"language-csharp\">  public partial class EvergineViewHandler : ViewHandler&lt;EvergineView, AndroidSurfaceView&gt;\n  {\n      private AndroidSurface androidSurface;\n      private AndroidWindowsSystem windowsSystem;\n\n      public EvergineViewHandler(IPropertyMapper mapper, CommandMapper commandMapper = null)\n         : base(mapper, commandMapper)\n      { }\n\n      public static void MapApplication(EvergineViewHandler handler, EvergineView evergineView)\n      {\n          handler.UpdateApplication(evergineView, evergineView.DisplayName);\n      }\n\n      internal void UpdateApplication(EvergineView view, string displayName)\n      {\n          if (view.Application is null) { return; }\n\n          \/\/ Register Windows system\n          view.Application.Container.RegisterInstance(this.windowsSystem);\n\n          \/\/ Creates XAudio device\n          var xaudio = new global::Evergine.OpenAL.ALAudioDevice();\n          view.Application.Container.RegisterInstance(xaudio);\n\n          System.Diagnostics.Stopwatch clockTimer = System.Diagnostics.Stopwatch.StartNew();\n          this.windowsSystem.Run(\n          () =&gt;\n          {\n              this.ConfigureGraphicsContext(view.Application as SneakerApp.MyApplication, this.androidSurface);\n              view.Application.Initialize();\n          },\n          () =&gt;\n          {\n              var gameTime = clockTimer.Elapsed;\n              clockTimer.Restart();\n\n              view.Application.UpdateFrame(gameTime);\n              view.Application.DrawFrame(gameTime);\n          });\n      }\n\n      protected override AndroidSurfaceView CreatePlatformView()\n      {\n          this.windowsSystem = new AndroidWindowsSystem(this.Context);\n          this.androidSurface = this.windowsSystem.CreateSurface(0, 0) as AndroidSurface;\n          return this.androidSurface.NativeSurface;\n      }\n\n      private void ConfigureGraphicsContext(MyApplication application, Surface surface)\n      {\n          var graphicsContext = new VKGraphicsContext();\n          graphicsContext.CreateDevice();\n          SwapChainDescription swapChainDescription = new SwapChainDescription()\n          {\n              SurfaceInfo = surface.SurfaceInfo,\n              Width = surface.Width,\n              Height = surface.Height,\n              ColorTargetFormat = PixelFormat.R8G8B8A8_UNorm,\n              ColorTargetFlags = TextureFlags.RenderTarget | TextureFlags.ShaderResource,\n              DepthStencilTargetFormat = PixelFormat.D24_UNorm_S8_UInt,\n              DepthStencilTargetFlags = TextureFlags.DepthStencil,\n              SampleCount = TextureSampleCount.None,\n              IsWindowed = true,\n              RefreshRate = 60,\n          };\n          var swapChain = graphicsContext.CreateSwapChain(swapChainDescription);\n          swapChain.VerticalSync = true;\n\n          var graphicsPresenter = application.Container.Resolve&lt;GraphicsPresenter&gt;();\n          var firstDisplay = new global::Evergine.Framework.Graphics.Display(surface, swapChain);\n          graphicsPresenter.AddDisplay(\"DefaultDisplay\", firstDisplay);\n\n          application.Container.RegisterInstance(graphicsContext);\n\n          surface.OnScreenSizeChanged += (_, args) =&gt;\n          {\n              swapChain.ResizeSwapChain(args.Height, args.Width);\n          };\n      }\n  }<\/code><\/pre>\n<p>In addition, the registration of the Evergine custom handler is performed in the <em>MauiProgram.cs<\/em> file of your project.<\/p>\n<pre><code class=\"language-csharp\">    public static class .NET MAUIProgram\n    {\n        public static .NET MAUIApp CreateMauiApp()\n        {\n            var builder = .NET MAUIApp.CreateBuilder();\n            builder\n                .UseMauiApp&lt;App&gt;()\n                .UseMauiEvergine()\n                .ConfigureFonts(fonts =&gt;\n                {\n                    fonts.AddFont(\"OpenSans-Regular.ttf\", \"OpenSansRegular\");\n                    fonts.AddFont(\"OpenSans-Semibold.ttf\", \"OpenSansSemibold\");\n                });\n\n#if DEBUG\n        builder.Logging.AddDebug();\n#endif\n\n            return builder.Build();\n        }\n    }<\/code><\/pre>\n<p>Finally, a 3D scene can be quite intricate and may comprise various assets, such as textures, materials, and models, etc. Evergine conveniently packages and transfers all 3D scene assets as raw assets to the device. To accomplish this, the Evergine template incorporates specific targets that label the 3D content as <em>MauiAsset<\/em> and injects it into the .NET MAUI target pipeline.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/evergine_target.jpg\" alt=\"Evergine target\" \/><\/p>\n<h2>Getting Started<\/h2>\n<p>After downloading and installing Evergine from the <a href=\"https:\/\/evergine.com\">official website<\/a>,  the Evergine launcher is the first thing you&#8217;ll encounter. It enables you to manage different versions, create new projects using various project templates, access sample projects, and find links to support and documentation.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/launcher.jpg\" alt=\"Launcher\" \/><\/p>\n<p>To initiate a new project from the Evergine launcher, navigate to the <em>My Projects<\/em> section and click on the <em>Add New Project<\/em> button<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/create_project.jpg\" alt=\"Create Project\" \/><\/p>\n<p>The project configuration window will open, allowing you to select the Project Name, the disk location for your project, and the desired Evergine version to use. Additionally, you have the option to choose the new .NET MAUI template.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/maui_template.jpg\" alt=\"MAUI template\" \/><\/p>\n<p>After clicking the <em>Create<\/em> button, Evergine Studio will open. You can then add any primitive object to the scene and attach a Spinner component with values {x:1, y:2, z:3} to enable rotation of the primitive.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/create_primitive.jpg\" alt=\"Create primitive\" \/><\/p>\n<p>To access the .NET MAUI solution, simply open it from the <em>File<\/em> menu in Evergine Studio. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/open_project.jpg\" alt=\"Open project\" \/><\/p>\n<p>When you launch the .NET MAUI solution in Visual Studio, you&#8217;ll discover two integrated projects within the solution. The first project is your Evergine project that you share between all templates, and the second is the .NET MAUI project, which references the Evergine project.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/project_explorer.jpg\" alt=\"Project_explorer\" \/><\/p>\n<p>Inside the .NET MAUI project, you&#8217;ll find the <em>Platform<\/em> folder, which houses platform-specific resources like the Android Manifest and Info.plist files. Within the Evergine folder, you&#8217;ll come across the EvergineView control. This control can be effortlessly integrated into your XAML pages, enabling you to include an Evergine canvas for rendering your 3D scenes.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/evergine_view.jpg\" alt=\"Evergine view\" \/><\/p>\n<p>To deploy your project on various platforms, utilize the <em>Run\/Deploy<\/em> button in Visual Studio. Please note that for iOS deployment, you&#8217;ll need to establish a connection between Visual Studio and a Mac, and have an iOS device (iPad or iPhone) linked to your Mac.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/project_deploy.jpg\" alt=\"Deploy\" \/><\/p>\n<p>Once you&#8217;ve successfully deployed your project within your .NET MAUI solution, you&#8217;ll attain results akin to the example depicted above. This showcases a fundamental XAML page in .NET MAUI, incorporating a Label and an EvergineView. While this serves as an example, you have the creative freedom to craft exceptional projects leveraging the latest .NET technologies and Evergine.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/project_result.jpg\" alt=\"Project result\" \/><\/p>\n<p>You can explore our showcase app, which demonstrates how to seamlessly blend mobile app UI with 3D content and effectively communicate between Evergine and .NET MAUI UI.<\/p>\n<p><strong>EverSneaks showcase app<\/strong>  <\/p>\n<p>Repository: https:\/\/github.com\/EvergineTeam\/EverSneaks\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/Header2.jpg\" alt=\"Shoes ecommerce showcase\" \/><\/p>\n<p><strong>CarRental showcase app<\/strong> (by <a href=\"https:\/\/github.com\/jsuarezruiz\">@Javier Suarez<\/a>)<\/p>\n<p>Repository: https:\/\/github.com\/jsuarezruiz\/netmaui-carrental-app-challenge\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2024\/01\/carrentalapp-maui.gif\" alt=\"Car Rental showcase\" \/><\/p>\n<h2>Evergine main resources<\/h2>\n<p>In the official Evergine website you can find a lot of interesting resources to getting started with Evergine, the following are the most important.<\/p>\n<ul>\n<li><strong>Evergine documentation:<\/strong> https:\/\/docs.evergine.com\/2023.9.28\/manual\/index.html<\/li>\n<li><strong>Samples repository:<\/strong> https:\/\/github.com\/EvergineTeam\/Samples<\/li>\n<li><strong>Video tutorials:<\/strong> https:\/\/evergine.com\/es\/videotutoriales\/<\/li>\n<li><strong>Youtube channel:<\/strong> https:\/\/www.youtube.com\/channel\/UCpA-X92rxM0OuywdVcir9mA<\/li>\n<li><strong>Feedback:<\/strong> https:\/\/github.com\/EvergineTeam\/Feedback\/issues<\/li>\n<li><strong>Contact:<\/strong> https:\/\/evergine.com\/contact\/ <\/li>\n<\/ul>\n<h2>Future<\/h2>\n<p>The current .NET MAUI template use .NET 7 stable version. After the .NET 8 stable version is released in November, we will update the .NET MAUI template to .NET 8 stable version to be available use the latest improvement and features.<\/p>\n<p>We have full confidence that the community can craft exceptionally attractive applications by harnessing the power of these technologies. We&#8217;re excited to see what you can create by combining 3D with .NET MAUI!.<\/p>\n<p>We eagerly await your feedback. Happy coding with Evergine and .NET MAUI!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>See how you can leverage Evergine to build 3D applications and content in .NET MAUI with just a few lines of code!<\/p>\n","protected":false},"author":132463,"featured_media":50175,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,7233],"tags":[7757,7758,7178],"class_list":["post-48457","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-maui","tag-3d","tag-3d-applications","tag-games"],"acf":[],"blog_post_summary":"<p>See how you can leverage Evergine to build 3D applications and content in .NET MAUI with just a few lines of code!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/48457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/132463"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=48457"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/48457\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/50175"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=48457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=48457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=48457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}