Skip to content

Commit d35d72b

Browse files
committed
Add SceneNodeIsland, but it hangs :-(
1 parent ed98180 commit d35d72b

File tree

5 files changed

+297
-0
lines changed

5 files changed

+297
-0
lines changed

Samples/Islands/WpfCalculator/CalculatorDemo/CalculatorDemo.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
<SubType>Code</SubType>
9898
</Compile>
9999
<Compile Include="App_Demo3.cs" />
100+
<Compile Include="HelmetScenario.cs" />
100101
<Compile Include="LottieIslandScenario.cs" />
101102
<Compile Include="MainWindow.cs">
102103
<DependentUpon>MainWindow.xaml</DependentUpon>
@@ -117,6 +118,7 @@
117118
<DependentUpon>Settings.settings</DependentUpon>
118119
<DesignTimeSharedInput>True</DesignTimeSharedInput>
119120
</Compile>
121+
<Compile Include="SceneNodeCommon.cs" />
120122
<!-- Demo4_Step2_AddIsland -->
121123
<Compile Include="WpfIslandHost.cs" />
122124
<!-- -->
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
}

Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<!-- Demo4_Step2_AddIsland -->
3030
<MenuItem Name="CreateDrawingIslandMenuItem" Click="CreateDrawingIslandMenuItem_Click" Header="Create DrawingIsland" />
3131
<MenuItem Name="CreateLottieIslandMenuItem" Click="CreateLottieIslandMenuItem_Click" Header="Create LottieIsland" />
32+
<MenuItem Name="CreateSceneNodeIslandMenuItem" Click="CreateSceneNodeIslandMenuItem_Click" Header="Create SceneNode" />
3233
<!-- -->
3334
<MenuItem Click="OnMenuExit" Header="Exit" />
3435
</MenuItem>

Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo4.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ private void CreateLottieIslandMenuItem_Click(object sender, RoutedEventArgs e)
3333
wpfIslandHost.DesktopChildSiteBridge.Connect(_lottieContentIsland.Island);
3434
}
3535

36+
private void CreateSceneNodeIslandMenuItem_Click(object sender, RoutedEventArgs e)
37+
{
38+
var wpfIslandHost = new WpfIslandHost(_compositor);
39+
var helmetIsland = HelmetScenario.CreateIsland(_compositor);
40+
41+
// After this, the WpfIslandHost will be live, and the DesktopChildSiteBridge will be available.
42+
DisplayAreaBorder.Child = wpfIslandHost;
43+
44+
wpfIslandHost.DesktopChildSiteBridge.Connect(helmetIsland);
45+
}
46+
3647
LottieContentIsland _lottieContentIsland;
3748
}
3849
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Windows.Foundation;
8+
using Windows.Storage.Streams;
9+
using Windows.Storage;
10+
using WinRT;
11+
using Microsoft.Graphics.Canvas.UI.Composition;
12+
using Microsoft.Graphics.Canvas;
13+
using Microsoft.Graphics.DirectX;
14+
using Microsoft.UI.Composition;
15+
using Microsoft.UI.Composition.Scenes;
16+
using Windows.Graphics;
17+
18+
class SceneNodeCommon
19+
{
20+
public static CompositionMipmapSurface LoadMipmapFromBitmap(
21+
CompositionGraphicsDevice graphicsDevice, CanvasBitmap canvasBitmap)
22+
{
23+
var size = new SizeInt32(2048, 2048);
24+
var mipmapSurface = graphicsDevice.CreateMipmapSurface(
25+
size,
26+
DirectXPixelFormat.B8G8R8A8UIntNormalized,
27+
DirectXAlphaMode.Premultiplied);
28+
29+
var drawDestRect = new Rect(0, 0, size.Width, size.Height);
30+
var drawSourceRect = new Rect(0, 0, size.Width, size.Height);
31+
for (uint level = 0; level < mipmapSurface.LevelCount; ++level)
32+
{
33+
// Draw the image to the surface
34+
var drawingSurface = mipmapSurface.GetDrawingSurfaceForLevel(level);
35+
36+
using (var session = CanvasComposition.CreateDrawingSession(drawingSurface))
37+
{
38+
session.Clear(Windows.UI.Color.FromArgb(0, 0, 0, 0));
39+
session.DrawImage(canvasBitmap, drawDestRect, drawSourceRect);
40+
}
41+
42+
drawDestRect = new Rect(0, 0, drawDestRect.Width / 2, drawDestRect.Height / 2);
43+
}
44+
45+
return mipmapSurface;
46+
}
47+
48+
public static SceneSurfaceMaterialInput CreateMaterial(
49+
Compositor compositor,
50+
CompositionMipmapSurface mipmap,
51+
SceneMeshRendererComponent rendererComponent,
52+
string mapping)
53+
{
54+
var materialInput = SceneSurfaceMaterialInput.Create(compositor);
55+
materialInput.Surface = mipmap;
56+
materialInput.BitmapInterpolationMode =
57+
CompositionBitmapInterpolationMode.MagLinearMinLinearMipLinear;
58+
59+
materialInput.WrappingUMode = SceneWrappingMode.Repeat;
60+
materialInput.WrappingVMode = SceneWrappingMode.Repeat;
61+
62+
rendererComponent.UVMappings[mapping] = SceneAttributeSemantic.TexCoord0;
63+
64+
return materialInput;
65+
}
66+
67+
public static async Task<MemoryBuffer> LoadMemoryBufferFromUriAsync(Uri uri)
68+
{
69+
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
70+
var buffer = await FileIO.ReadBufferAsync(file);
71+
72+
return CopyToMemoryBuffer(buffer);
73+
}
74+
75+
public static MemoryBuffer CopyToMemoryBuffer(IBuffer buffer)
76+
{
77+
var dataReader = DataReader.FromBuffer(buffer);
78+
79+
var memBuffer = new MemoryBuffer(buffer.Length);
80+
var memBufferRef = memBuffer.CreateReference();
81+
var memBufferByteAccess = memBufferRef.As<IMemoryBufferByteAccess>();
82+
83+
unsafe
84+
{
85+
byte* bytes = null;
86+
uint capacity;
87+
memBufferByteAccess.GetBuffer(&bytes, &capacity);
88+
89+
for (int i = 0; i < capacity; ++i)
90+
{
91+
bytes[i] = dataReader.ReadByte();
92+
}
93+
}
94+
95+
return memBuffer;
96+
}
97+
98+
99+
public static MemoryBuffer CopyToMemoryBuffer(byte[] a)
100+
{
101+
MemoryBuffer mb = new MemoryBuffer((uint)a.Length);
102+
var mbr = mb.CreateReference();
103+
var mba = mbr.As<IMemoryBufferByteAccess>();
104+
unsafe
105+
{
106+
byte* bytes = null;
107+
uint capacity;
108+
mba.GetBuffer(&bytes, &capacity);
109+
for (int i = 0; i < capacity; ++i)
110+
{
111+
bytes[i] = a[i];
112+
}
113+
}
114+
115+
return mb;
116+
}
117+
118+
119+
120+
[ComImport,
121+
Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d"),
122+
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
123+
public interface IMemoryBufferByteAccess
124+
{
125+
unsafe void GetBuffer(byte** bytes, uint* capacity);
126+
}
127+
}

0 commit comments

Comments
 (0)