|
| 1 | +// Copyright (c) Microsoft Corporation. |
| 2 | +// Licensed under the MIT License. |
| 3 | + |
| 4 | +using System; |
| 5 | +using System.Collections.Generic; |
| 6 | +using System.Numerics; |
| 7 | +using System.Runtime.InteropServices; |
| 8 | + |
| 9 | +using Windows.Foundation; |
| 10 | +using Windows.Graphics; |
| 11 | +using Windows.Storage; |
| 12 | +using Windows.Storage.Streams; |
| 13 | + |
| 14 | +using Microsoft.Graphics.Canvas; |
| 15 | +using Microsoft.Graphics.Canvas.UI.Composition; |
| 16 | +using Microsoft.Graphics.DirectX; |
| 17 | +using Microsoft.UI.Composition; |
| 18 | +using Microsoft.UI.Composition.Scenes; |
| 19 | +using Microsoft.UI.Content; |
| 20 | +using System.Threading.Tasks; |
| 21 | + |
| 22 | +class HelmetScenario |
| 23 | +{ |
| 24 | + public static ContentIsland CreateIsland(Compositor compositor) |
| 25 | + { |
| 26 | + var visual = LoadScene_DamagedHelmet(compositor); |
| 27 | + |
| 28 | + var island = ContentIsland.Create(visual); |
| 29 | + return island; |
| 30 | + } |
| 31 | + |
| 32 | + private static Visual LoadScene_DamagedHelmet(Compositor compositor) |
| 33 | + { |
| 34 | + // Initialize Win2D, used for loading bitmaps. |
| 35 | + |
| 36 | + var canvasDevice = new CanvasDevice(); |
| 37 | + var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice( |
| 38 | + compositor, canvasDevice); |
| 39 | + |
| 40 | + |
| 41 | + // Create the Visuals and SceneNode structure, along with default rotation animations. |
| 42 | + |
| 43 | + var sceneVisual = SceneVisual.Create(compositor); |
| 44 | + sceneVisual.RelativeOffsetAdjustment = new Vector3(0.5f, 0.5f, 0.0f); |
| 45 | + |
| 46 | + var worldNode = SceneNode.Create(compositor); |
| 47 | + sceneVisual.Root = worldNode; |
| 48 | + |
| 49 | + var rotateAngleAnimation = compositor.CreateScalarKeyFrameAnimation(); |
| 50 | + rotateAngleAnimation.InsertKeyFrame(0.0f, 0.0f); |
| 51 | + rotateAngleAnimation.InsertKeyFrame(0.5f, 360.0f); |
| 52 | + rotateAngleAnimation.InsertKeyFrame(1.0f, 0.0f); |
| 53 | + rotateAngleAnimation.Duration = TimeSpan.FromSeconds(15); |
| 54 | + rotateAngleAnimation.IterationBehavior = AnimationIterationBehavior.Forever; |
| 55 | + worldNode.Transform.RotationAxis = new Vector3(0, 1, 0); |
| 56 | + worldNode.Transform.StartAnimation("RotationAngleInDegrees", rotateAngleAnimation); |
| 57 | + |
| 58 | + var sceneNode0 = SceneNode.Create(compositor); |
| 59 | + sceneNode0.Transform.Scale = new Vector3(350); |
| 60 | + sceneNode0.Transform.Orientation = new Quaternion(0.70710683f, 0.0f, 0.0f, 0.70710683f); |
| 61 | + worldNode.Children.Add(sceneNode0); |
| 62 | + |
| 63 | + var sceneNodeForTheGLTFMesh0 = SceneNode.Create(compositor); |
| 64 | + sceneNode0.Children.Add(sceneNodeForTheGLTFMesh0); |
| 65 | + |
| 66 | + |
| 67 | + // Load all file data in parallel: |
| 68 | + // - Although Scene Graph objects prefer a UI thread, Win2D can load and create the bitmaps |
| 69 | + // on parallel background threads. |
| 70 | + |
| 71 | + var vertexData = SceneNodeCommon.LoadMemoryBufferFromUriAsync( |
| 72 | + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet6.bin")); |
| 73 | + |
| 74 | + var normalData = SceneNodeCommon.LoadMemoryBufferFromUriAsync( |
| 75 | + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet7.bin")); |
| 76 | + |
| 77 | + var texCoordData = SceneNodeCommon.LoadMemoryBufferFromUriAsync( |
| 78 | + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet8.bin")); |
| 79 | + |
| 80 | + var indexData = SceneNodeCommon.LoadMemoryBufferFromUriAsync( |
| 81 | + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet9.bin")); |
| 82 | + |
| 83 | + var canvasBitmap0 = CanvasBitmap.LoadAsync( |
| 84 | + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet1.bmp")).AsTask(); |
| 85 | + |
| 86 | + var canvasBitmap1 = CanvasBitmap.LoadAsync( |
| 87 | + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet2.bmp")).AsTask(); |
| 88 | + |
| 89 | + var canvasBitmap2 = CanvasBitmap.LoadAsync( |
| 90 | + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet3.bmp")).AsTask(); |
| 91 | + |
| 92 | + var canvasBitmap3 = CanvasBitmap.LoadAsync( |
| 93 | + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet4.bmp")).AsTask(); |
| 94 | + |
| 95 | + var canvasBitmap4 = CanvasBitmap.LoadAsync( |
| 96 | + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet5.bmp")).AsTask(); |
| 97 | + |
| 98 | + Task.WaitAll( |
| 99 | + vertexData, normalData, texCoordData, indexData, |
| 100 | + canvasBitmap0, canvasBitmap1, canvasBitmap2, canvasBitmap3, canvasBitmap4); |
| 101 | + |
| 102 | + |
| 103 | + // Generate mipmaps from the bitmaps, which are needed for 3D rendering. |
| 104 | + |
| 105 | + var materialInput0 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap0.Result); |
| 106 | + var materialInput1 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap1.Result); |
| 107 | + var materialInput2 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap2.Result); |
| 108 | + var materialInput3 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap3.Result); |
| 109 | + var materialInput4 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap4.Result); |
| 110 | + |
| 111 | + |
| 112 | + // Copy loaded binary data into mesh: verticies, normals, ... |
| 113 | + |
| 114 | + var mesh0 = SceneMesh.Create(compositor); |
| 115 | + mesh0.PrimitiveTopology = DirectXPrimitiveTopology.TriangleList; |
| 116 | + mesh0.FillMeshAttribute(SceneAttributeSemantic.Vertex, DirectXPixelFormat.R32G32B32Float, vertexData.Result); |
| 117 | + mesh0.FillMeshAttribute(SceneAttributeSemantic.Normal, DirectXPixelFormat.R32G32B32Float, normalData.Result); |
| 118 | + mesh0.FillMeshAttribute(SceneAttributeSemantic.TexCoord0, DirectXPixelFormat.R32G32Float, texCoordData.Result); |
| 119 | + mesh0.FillMeshAttribute(SceneAttributeSemantic.Index, DirectXPixelFormat.R16UInt, indexData.Result); |
| 120 | + |
| 121 | + |
| 122 | + // Initialize the material with different texture inputs (color, roughness, normals, ...) |
| 123 | + |
| 124 | + var sceneMaterial0 = SceneMetallicRoughnessMaterial.Create(compositor); |
| 125 | + |
| 126 | + var renderComponent0 = SceneMeshRendererComponent.Create(compositor); |
| 127 | + renderComponent0.Mesh = mesh0; |
| 128 | + renderComponent0.Material = sceneMaterial0; |
| 129 | + sceneNodeForTheGLTFMesh0.Components.Add(renderComponent0); |
| 130 | + |
| 131 | + sceneMaterial0.BaseColorFactor = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); |
| 132 | + sceneMaterial0.BaseColorInput = SceneNodeCommon.CreateMaterial( |
| 133 | + compositor, materialInput0, renderComponent0, "BaseColorInput"); ; |
| 134 | + |
| 135 | + sceneMaterial0.RoughnessFactor = 1.0f; |
| 136 | + sceneMaterial0.MetallicFactor = 1.0f; |
| 137 | + sceneMaterial0.MetallicRoughnessInput = SceneNodeCommon.CreateMaterial( |
| 138 | + compositor, materialInput1, renderComponent0, "MetallicRoughnessInput"); |
| 139 | + |
| 140 | + sceneMaterial0.NormalScale = 1.0f; |
| 141 | + sceneMaterial0.NormalInput = SceneNodeCommon.CreateMaterial( |
| 142 | + compositor, materialInput2, renderComponent0, "NormalInput"); |
| 143 | + |
| 144 | + sceneMaterial0.OcclusionStrength = 1.0f; |
| 145 | + sceneMaterial0.OcclusionInput = SceneNodeCommon.CreateMaterial( |
| 146 | + compositor, materialInput3, renderComponent0, "OcclusionInput"); |
| 147 | + |
| 148 | + sceneMaterial0.AlphaMode = SceneAlphaMode.Opaque; |
| 149 | + sceneMaterial0.IsDoubleSided = false; |
| 150 | + sceneMaterial0.EmissiveFactor = new Vector3(1.0f, 1.0f, 1.0f); |
| 151 | + sceneMaterial0.EmissiveInput = SceneNodeCommon.CreateMaterial( |
| 152 | + compositor, materialInput4, renderComponent0, "EmissiveInput"); |
| 153 | + |
| 154 | + return sceneVisual; |
| 155 | + } |
| 156 | +} |
0 commit comments