├── .gitignore
├── Experimental
└── CameraComponent
│ ├── Animatable.cs
│ ├── Camera.cs
│ ├── CameraComponent.csproj
│ ├── FirstPersonCamera.cs
│ ├── ModelViewer.xaml
│ ├── ModelViewer.xaml.cs
│ ├── OrbitalCamera.cs
│ ├── OrthographicProjection.cs
│ ├── PerspectiveProjection.cs
│ ├── Projection.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ └── Viewport.cs
├── LICENSE.md
├── README.md
├── SceneLoader.sln
├── SceneLoader
├── Bounds3D.cpp
├── Bounds3D.h
├── GLTFVisitor.cpp
├── GLTFVisitor.h
├── GLTFVisitor_Camera.cpp
├── GLTFVisitor_Image.cpp
├── GLTFVisitor_Material.cpp
├── GLTFVisitor_Mesh.cpp
├── GLTFVisitor_MeshPrimitive.cpp
├── GLTFVisitor_Node.cpp
├── GLTFVisitor_Sampler.cpp
├── GLTFVisitor_Skin.cpp
├── GLTFVisitor_Texture.cpp
├── NugetPackager
│ ├── SceneLoaderComponent.nuspec
│ ├── SceneLoaderComponent.props
│ └── SceneLoaderComponent.targets
├── SceneLoader.cpp
├── SceneLoader.h
├── SceneLoader.vcxproj
├── SceneLoader.vcxproj.filters
├── SceneLoaderComponent.def
├── SceneLoaderComponent.idl
├── SceneResourceSet.cpp
├── SceneResourceSet.h
├── UtilForIntermingledNamespaces.cpp
├── UtilForIntermingledNamespaces.h
├── packages.config
├── pch.cpp
├── pch.h
└── readme.md
├── TestViewer
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── DamagedHelmet.gltf
│ ├── LockScreenLogo.scale-200.png
│ ├── OrientationTest.gltf
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ └── Wide310x150Logo.scale-200.png
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── TestViewer.csproj
└── TestViewer_TemporaryKey.pfx
├── azure-pipelines.yml
├── build
├── Build.bat
├── Clean.bat
├── Find-WindowsSDKVersions.ps1
├── Install-WindowsSDK.ps1
├── Install-WindowsSdkISO.ps1
├── Sign-Package.ps1
├── SignClientSettings.json
├── StyleXaml.bat
├── UpdateHeaders.bat
├── build.cake
├── build.ps1
├── header.txt
└── nuget.png
├── settings.xamlstyler
└── version.json
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | build/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # Visual Studio 2017 auto generated files
34 | Generated\ Files/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 |
44 | # Build Results of an ATL Project
45 | [Dd]ebugPS/
46 | [Rr]eleasePS/
47 | dlldata.c
48 |
49 | # Benchmark Results
50 | BenchmarkDotNet.Artifacts/
51 |
52 | # .NET Core
53 | project.lock.json
54 | project.fragment.lock.json
55 | artifacts/
56 | **/Properties/launchSettings.json
57 |
58 | # StyleCop
59 | StyleCopReport.xml
60 |
61 | # Files built by Visual Studio
62 | *_i.c
63 | *_p.c
64 | *_i.h
65 | *.ilk
66 | *.meta
67 | *.obj
68 | *.iobj
69 | *.pch
70 | *.pdb
71 | *.ipdb
72 | *.pgc
73 | *.pgd
74 | *.rsp
75 | *.sbr
76 | *.tlb
77 | *.tli
78 | *.tlh
79 | *.tmp
80 | *.tmp_proj
81 | *.log
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 |
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 |
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 |
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 |
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 |
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 |
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 |
149 | # Web workbench (sass)
150 | .sass-cache/
151 |
152 | # Installshield output folder
153 | [Ee]xpress/
154 |
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 |
165 | # Click-Once directory
166 | publish/
167 |
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 |
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 |
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 |
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 |
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 |
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 |
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 |
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 |
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 |
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 |
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 |
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 |
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 |
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 |
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 |
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 |
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 |
267 | # Visual Studio 6 build log
268 | *.plg
269 |
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 |
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 |
295 | # CodeRush
296 | .cr/
297 |
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 |
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 |
306 | # Tabs Studio
307 | *.tss
308 |
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 |
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 |
318 | # OpenCover UI analysis results
319 | OpenCover/
320 |
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 |
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 |
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 |
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 |
333 | # Nuget Packager
334 | */NugetPackager
--------------------------------------------------------------------------------
/Experimental/CameraComponent/Animatable.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using Windows.UI.Composition;
6 |
7 | namespace CameraComponent
8 | {
9 | ///
10 | /// An interface that defines functions non-Composition objects can implement to become animatable.
11 | ///
12 | public interface Animatable
13 | {
14 | ///
15 | /// Returns an object's set of animatable properties.
16 | ///
17 | CompositionPropertySet GetPropertySet();
18 |
19 | ///
20 | /// Starts a given animation on the specified property.
21 | ///
22 | /// The name of the property to be animated.
23 | /// The animation being applied.
24 | void StartAnimation(string propertyName, CompositionAnimation animation);
25 |
26 | ///
27 | /// Stops any animations on the specified property.
28 | ///
29 | /// The name of the property whose animations we are stopping.
30 | void StopAnimation(string propertyName);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/Camera.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Numerics;
6 |
7 | namespace CameraComponent
8 | {
9 | ///
10 | /// An interface that defines properties and functions that a Camera object must implement.
11 | ///
12 | public interface Camera : Animatable
13 | {
14 | ///
15 | /// A reference to a class that implements the Projection interace.
16 | ///
17 | Projection Projection { get; set; }
18 |
19 | ///
20 | /// Returns the matrix created using the Camera's position and rotation in world space.
21 | ///
22 | /// /// A Matrix4x4 that is the product of the matrices representing the camera's translation and rotation.
23 | Matrix4x4 GetViewMatrix();
24 |
25 | ///
26 | /// Returns the matrix created using the Camera's view matrix and the Camera's Projection's matrix.
27 | ///
28 | /// A Matrix4x4 that is the the product of the matrices representing the camera's transformations in world space and
29 | /// the matrix created by the Camera's Projection property.
30 | Matrix4x4 GetModelViewProjectionMatrix();
31 | }
32 | }
--------------------------------------------------------------------------------
/Experimental/CameraComponent/CameraComponent.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}
8 | winmdobj
9 | Properties
10 | CameraComponent
11 | CameraComponent
12 | en-US
13 | UAP
14 | 10.0.18362.0
15 | 10.0.18362.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | false
20 |
21 |
22 | AnyCPU
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
28 | prompt
29 | 4
30 |
31 |
32 | AnyCPU
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE;NETFX_CORE;WINDOWS_UWP
37 | prompt
38 | 4
39 |
40 |
41 | x86
42 | true
43 | bin\x86\Debug\
44 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
45 | ;2008
46 | full
47 | false
48 | prompt
49 | false
50 |
51 |
52 |
53 |
54 | x86
55 | bin\x86\Release\
56 | TRACE;NETFX_CORE;WINDOWS_UWP
57 | true
58 | ;2008
59 | pdbonly
60 | false
61 | prompt
62 |
63 |
64 | ARM
65 | true
66 | bin\ARM\Debug\
67 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
68 | ;2008
69 | full
70 | false
71 | prompt
72 |
73 |
74 | ARM
75 | bin\ARM\Release\
76 | TRACE;NETFX_CORE;WINDOWS_UWP
77 | true
78 | ;2008
79 | pdbonly
80 | false
81 | prompt
82 |
83 |
84 | ARM64
85 | true
86 | bin\ARM64\Debug\
87 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
88 | ;2008
89 | full
90 | false
91 | prompt
92 |
93 |
94 | ARM64
95 | bin\ARM64\Release\
96 | TRACE;NETFX_CORE;WINDOWS_UWP
97 | true
98 | ;2008
99 | pdbonly
100 | false
101 | prompt
102 |
103 |
104 | x64
105 | true
106 | bin\x64\Debug\
107 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
108 | ;2008
109 | full
110 | false
111 | prompt
112 |
113 |
114 | x64
115 | bin\x64\Release\
116 | TRACE;NETFX_CORE;WINDOWS_UWP
117 | true
118 | ;2008
119 | pdbonly
120 | false
121 | prompt
122 |
123 |
124 | PackageReference
125 |
126 |
127 |
128 |
129 |
130 |
131 | ModelViewer.xaml
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | 6.2.8
143 |
144 |
145 |
146 |
147 | Designer
148 | MSBuild:Compile
149 |
150 |
151 |
152 |
153 | {88c4d662-8669-433b-8a8b-47b3a17e3c6e}
154 | SceneLoaderComponent
155 |
156 |
157 |
158 | 14.0
159 |
160 |
161 |
162 |
163 |
164 |
171 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/FirstPersonCamera.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Numerics;
7 | using Windows.UI.Composition;
8 |
9 | namespace CameraComponent
10 | {
11 | ///
12 | /// A class that defines a FirstPersonCamera that has a position in 3D world space and rotates about the x,y, and z axes.
13 | /// Implements the Camera and Animatable interfaces.
14 | ///
15 | public sealed class FirstPersonCamera : Camera
16 | {
17 | private Compositor _compositor;
18 | private Projection _projection;
19 | private CompositionPropertySet _propertySet;
20 |
21 | ///
22 | /// Creates a FirstPersonCamera with default properties.
23 | /// Position = Vector3.Zero
24 | /// Yaw = 0
25 | /// Pitch = 0
26 | /// Roll = 0
27 | /// ModelViewProjectionMatrix = Matrix4x4.Identity
28 | ///
29 | ///
30 | /// Thrown when constructor is passed a null value.
31 | public FirstPersonCamera(Compositor compositor)
32 | {
33 | if (compositor == null)
34 | {
35 | throw new System.ArgumentException("Compositor cannot be null");
36 | }
37 |
38 | _compositor = compositor;
39 |
40 | // Create the properties for the camera
41 | _propertySet = _compositor.CreatePropertySet();
42 | _propertySet.InsertVector3("Position", Vector3.Zero);
43 | _propertySet.InsertScalar("Yaw", 0f);
44 | _propertySet.InsertScalar("Pitch", 0f);
45 | _propertySet.InsertScalar("Roll", 0f);
46 | _propertySet.InsertMatrix4x4("ModelViewProjectionMatrix", Matrix4x4.Identity);
47 |
48 | // Default is an orthographic projection
49 | Projection = new OrthographicProjection(_compositor);
50 | }
51 |
52 | ///
53 | /// Camera's rotation about the y-axis in radians.
54 | /// Rotates counterclockwise from 0 to 2Pi.
55 | ///
56 | public float Yaw
57 | {
58 | get
59 | {
60 | float curr;
61 | _propertySet.TryGetScalar("Yaw", out curr);
62 | return curr;
63 | }
64 | set
65 | {
66 | _propertySet.InsertScalar("Yaw", value);
67 | }
68 | }
69 |
70 | ///
71 | /// Camera's rotation about the x-axis in radians.
72 | /// Rotates counterclockwise from 0 to 2Pi.
73 | ///
74 | public float Pitch
75 | {
76 | get
77 | {
78 | float curr;
79 | _propertySet.TryGetScalar("Pitch", out curr);
80 | return curr;
81 | }
82 | set
83 | {
84 | _propertySet.InsertScalar("Pitch", value);
85 | }
86 | }
87 |
88 | ///
89 | /// Camera's rotation about the z-axis in radians.
90 | /// Rotates counterclockwise from 0 to 2Pi.
91 | ///
92 | public float Roll
93 | {
94 | get
95 | {
96 | float curr;
97 | _propertySet.TryGetScalar("Roll", out curr);
98 | return curr;
99 | }
100 | set
101 | {
102 | _propertySet.InsertScalar("Roll", value);
103 | }
104 | }
105 |
106 | ///
107 | /// Camera's position in 3D world space.
108 | ///
109 | public Vector3 Position
110 | {
111 | get
112 | {
113 | Vector3 curr;
114 | _propertySet.TryGetVector3("Position", out curr);
115 | return curr;
116 | }
117 | set
118 | {
119 | _propertySet.InsertVector3("Position", value);
120 | }
121 | }
122 |
123 | ///
124 | /// The camera's reference to an object that implements the Projection interace.
125 | /// When setting, this property starts animations on the camera's ModelViewProjectionMatrix property.
126 | ///
127 | /// When set to null, the ModelViewProjectionProperty is animated using an OrthographicProjection with the
128 | /// default values of: Height = 100, Width = 100, Near = 1, Far = 1000.
129 | public Projection Projection
130 | {
131 | get => _projection;
132 | set
133 | {
134 | _projection = value;
135 |
136 | // create view matrix based on the camera's rotation and position
137 | var matPos = "Matrix4x4.CreateTranslation(-FPCamera.Position)";
138 | var matRoll = "Matrix4x4.CreateFromAxisAngle(Vector3(0, 0, 1), -FPCamera.Roll)";
139 | var matPitch = "Matrix4x4.CreateFromAxisAngle(Vector3(1, 0, 0), -FPCamera.Pitch)";
140 | var matYaw = "Matrix4x4.CreateFromAxisAngle(Vector3(0, 1, 0), -FPCamera.Yaw)";
141 | var viewMat = matPos + "*" + matYaw + "*" + matPitch + "*" + matRoll;
142 |
143 | // create a matrix that is the product of the camera's view matrix and the projection's projection matrix
144 | var modelViewProjMatExpression = _compositor.CreateExpressionAnimation();
145 | if (_projection == null) // if null then the default is an orthographic projection
146 | {
147 | OrthographicProjection defaultProj = new OrthographicProjection(_compositor);
148 | modelViewProjMatExpression.Expression = viewMat + "*" + "DefaultProjection.ProjectionMatrix";
149 | modelViewProjMatExpression.SetReferenceParameter("FPCamera", _propertySet);
150 | modelViewProjMatExpression.SetReferenceParameter("DefaultProjection", Projection.GetPropertySet());
151 | }
152 | else
153 | {
154 | modelViewProjMatExpression.Expression = viewMat + "*" + "Projection.ProjectionMatrix";
155 | modelViewProjMatExpression.SetReferenceParameter("FPCamera", _propertySet);
156 | modelViewProjMatExpression.SetReferenceParameter("Projection", Projection.GetPropertySet());
157 | }
158 |
159 | StartAnimation("ModelViewProjectionMatrix", modelViewProjMatExpression);
160 | }
161 | }
162 |
163 | ///
164 | /// Rotates the camera's yaw and pitch to look in the given direction.
165 | ///
166 | ///
167 | public void SetLookDirection(Vector3 direction)
168 | {
169 | if (direction != Vector3.Zero)
170 | {
171 | direction = Vector3.Normalize(direction);
172 | }
173 |
174 | direction.X *= -1;
175 | Yaw = (MathF.PI / 2f) + MathF.Atan2(direction.Z, direction.X);
176 | Pitch = MathF.Asin(direction.Y);
177 | }
178 |
179 | ///
180 | /// Returns the matrix created from the camera's translation and rotation transformations.
181 | ///
182 | /// A Matrix4x4 that is the product of the matrices created from the camera's position, yaw, pitch, and roll.
183 | public Matrix4x4 GetViewMatrix()
184 | {
185 | // create view matrix based on the camera's rotation and position
186 | Matrix4x4 matPos = Matrix4x4.CreateTranslation(-Position);
187 | Matrix4x4 matRoll = Matrix4x4.CreateFromAxisAngle(new Vector3(0, 0, 1), -Roll);
188 | Matrix4x4 matPitch = Matrix4x4.CreateFromAxisAngle(new Vector3(1, 0, 0), -Pitch);
189 | Matrix4x4 matYaw = Matrix4x4.CreateFromAxisAngle(new Vector3(0, 1, 0), -Yaw);
190 |
191 | return matPos * matYaw * matPitch * matRoll;
192 | }
193 |
194 | ///
195 | /// Returns that a matrix created from the camera's view matrix and it's Projection's projection matrix.
196 | ///
197 | /// A Matrix4x4 that is the product of matrices created from the Camera's position, yaw, pitch, and roll and its Projection's projection matrix.
198 | public Matrix4x4 GetModelViewProjectionMatrix()
199 | {
200 | return GetViewMatrix() * Projection.GetProjectionMatrix();
201 | }
202 |
203 | ///
204 | /// Returns the camera's set of animatable properties.
205 | ///
206 | /// A CompositionPropertySet holding the camera's properties.
207 | public CompositionPropertySet GetPropertySet()
208 | {
209 | return _propertySet;
210 | }
211 |
212 | ///
213 | /// Starts a given animation on the specified property.
214 | ///
215 | /// The name of the property to be animated.
216 | /// The animation being applied.
217 | public void StartAnimation(string propertyName, CompositionAnimation animation)
218 | {
219 | _propertySet.StartAnimation(propertyName, animation);
220 | }
221 |
222 | ///
223 | /// Stops any animations on the specified property.
224 | ///
225 | /// The name of the property whose animations we are stopping.
226 | public void StopAnimation(string propertyName)
227 | {
228 | _propertySet.StopAnimation(propertyName);
229 | }
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/ModelViewer.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/ModelViewer.xaml.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Controls;
8 | using Windows.UI.Xaml.Input;
9 | using SceneLoaderComponent;
10 | using Windows.UI.Composition;
11 | using Windows.UI.Composition.Scenes;
12 | using System.Numerics;
13 | using Windows.UI.Xaml.Hosting;
14 | using Windows.Storage;
15 | using System.Threading.Tasks;
16 |
17 | // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
18 |
19 | namespace CameraComponent
20 | {
21 | public sealed partial class ModelViewer : UserControl
22 | {
23 | private Compositor _compositor;
24 | private SceneVisual _sceneVisual;
25 | private Viewport _viewport;
26 | private OrbitalCamera _camera;
27 |
28 | private bool _mouseDowned;
29 | private Vector2 _mouseDownLocation;
30 |
31 | public ModelViewer()
32 | {
33 | this.InitializeComponent();
34 |
35 | // Create a camera and a ContainerVisual
36 | _compositor = Window.Current.Compositor;
37 | var root = _compositor.CreateContainerVisual();
38 | root.Size = new Vector2(1000, 1000);
39 | ElementCompositionPreview.SetElementChildVisual(this, root);
40 |
41 | // create a SceneVisual and insert it into the visual tree
42 | _sceneVisual = SceneVisual.Create(_compositor);
43 | root.Children.InsertAtTop(_sceneVisual);
44 |
45 | // instantiate viewport and assign it "good" default values
46 | _viewport = new Viewport(_compositor);
47 | _viewport.AttachToVisual(_sceneVisual);
48 | _viewport.Size = Target.ActualSize;
49 | _viewport.Offset = new Vector3(_viewport.Size / 2f, 0f);
50 |
51 | // instantiate camera and assign it "good" default values
52 | _camera = new OrbitalCamera(_compositor);
53 | _camera.Target = new Vector3(0f, 0f, 0f);
54 | _camera.Radius = 600f;
55 | _camera.Theta = 0f;
56 | _camera.Phi = MathF.PI / 4;
57 |
58 | // instantiate projection and assign it "good" default values
59 | PerspectiveProjection projection = new PerspectiveProjection(_compositor);
60 | projection.Fov = MathF.PI / 2;
61 |
62 | _camera.Projection = projection;
63 | _viewport.Camera = _camera;
64 |
65 | // add event handler for chaning target size
66 | Target.SizeChanged += Target_SizeChanged;
67 |
68 | // event handlers for pointer events
69 | Target.PointerWheelChanged += Target_PointerWheelChanged;
70 | Target.PointerPressed += Target_PointerPressed;
71 | Target.PointerReleased += Target_PointerReleased;
72 | Target.PointerMoved += Target_PointerMoved;
73 |
74 | Window.Current.CoreWindow.PointerReleased += CoreWindow_PointerReleased;
75 | }
76 |
77 | private void CoreWindow_PointerReleased(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
78 | {
79 | _mouseDowned = false;
80 | }
81 |
82 | private void Target_SizeChanged(object sender, SizeChangedEventArgs e)
83 | {
84 | _viewport.Size = e.NewSize.ToVector2();
85 | }
86 |
87 | private void Target_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
88 | {
89 | // positive if scroll away from the user, negative if scroll toward the user
90 | int scrollSign = Math.Sign(e.GetCurrentPoint(Target).Properties.MouseWheelDelta);
91 |
92 | // determines how much to increase or decrease camera's radius by with each scroll
93 | // smaller numbers correspond to greater changes in radius
94 | float sensitivity = 0.95f;
95 |
96 | // scroll away from you
97 | if (scrollSign > 0)
98 | {
99 | _camera.Radius *= sensitivity;
100 | }
101 | // scroll towards you
102 | else if (scrollSign < 0)
103 | {
104 | _camera.Radius *= 1 + (1 - sensitivity);
105 | }
106 | }
107 |
108 | private void Target_PointerPressed(object sender, PointerRoutedEventArgs e)
109 | {
110 | // use to determine how much to rotate camera by, based on size of change in pointer position
111 | _mouseDownLocation = e.GetCurrentPoint(Target).Position.ToVector2();
112 |
113 | _mouseDowned = true;
114 | }
115 |
116 | private void Target_PointerReleased(object sender, PointerRoutedEventArgs e)
117 | {
118 | // prohibit mouse from changing rotation if the mouse button isn't pressed
119 | _mouseDowned = false;
120 | }
121 |
122 | private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
123 | {
124 | if (_mouseDowned)
125 | {
126 | // rotate proportionately to the size of the mouse movement
127 | Vector2 newPos = e.GetCurrentPoint(Target).Position.ToVector2();
128 | float thetaDelta = newPos.X - _mouseDownLocation.X;
129 | float phiDelta = newPos.Y - _mouseDownLocation.Y;
130 |
131 | _mouseDownLocation = newPos;
132 |
133 | // higher number corresponds to faster rotation
134 | float sensitivity = 0.005f;
135 |
136 | // changes camera's phi and theta based on the sensitivity and size of the mouse movement
137 | _camera.Theta -= sensitivity * thetaDelta;
138 | _camera.Phi -= sensitivity * phiDelta;
139 | }
140 | }
141 |
142 | public string GltfFile
143 | {
144 | get { return (string)GetValue(GltfFileProperty); }
145 | set
146 | {
147 | SetValue(GltfFileProperty, value);
148 | LoadGltfFile();
149 | }
150 | }
151 |
152 | private static readonly DependencyProperty GltfFileProperty =
153 | DependencyProperty.Register("GltfFile", typeof(string), typeof(ModelViewer), null);
154 |
155 | private async void LoadGltfFile()
156 | {
157 | _sceneVisual.Root = await LoadGLTF(new Uri(GltfFile));
158 | }
159 |
160 | async Task LoadGLTF(Uri uri)
161 | {
162 | var storageFile = await StorageFile.GetFileFromApplicationUriAsync(uri);
163 | var buffer = await FileIO.ReadBufferAsync(storageFile);
164 |
165 | var loader = new SceneLoader();
166 | return loader.Load(buffer, _compositor);
167 | }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/OrbitalCamera.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Numerics;
7 | using Windows.UI.Composition;
8 |
9 | namespace CameraComponent
10 | {
11 | ///
12 | /// A class that defines an OrbitalCamera that orbits around a point in world space.
13 | /// Implements the Camera and Animatable interfaces.
14 | ///
15 | public sealed class OrbitalCamera : Camera
16 | {
17 | private Compositor _compositor;
18 | private FirstPersonCamera _fpCam;
19 | private CompositionPropertySet _propertySet;
20 |
21 | ///
22 | /// Creates an OrbitalCamera with default properties.
23 | /// Target = Vector3.Zero
24 | /// Phi = 0
25 | /// Theta = 0
26 | /// Radius = 300
27 | /// ModelViewProjectionMatrix = Matrix4x4.Identity
28 | ///
29 | ///
30 | /// Thrown when constructor is passed a null value.
31 | public OrbitalCamera(Compositor compositor)
32 | {
33 | if (compositor == null)
34 | {
35 | throw new System.ArgumentException("Compositor cannot be null");
36 | }
37 |
38 | _compositor = compositor;
39 | _fpCam = new FirstPersonCamera(_compositor);
40 | _propertySet = _compositor.CreatePropertySet();
41 |
42 | float epsilon = 0.0001f;
43 |
44 | // Create the properties for the camera
45 | _propertySet.InsertVector3("Target", Vector3.Zero);
46 | _propertySet.InsertScalar("Phi", epsilon);
47 | _propertySet.InsertScalar("Theta", 0f);
48 | _propertySet.InsertScalar("Radius", 300f);
49 | _propertySet.InsertMatrix4x4("ModelViewProjectionMatrix", Matrix4x4.Identity);
50 |
51 | // Connect orbital camera's properties to the _fpCam's properties
52 | StartAnimationsOnFPCamera();
53 | }
54 |
55 | ///
56 | /// Point in 3D world space that the camera orbits about and centers it's view on.
57 | ///
58 | public Vector3 Target
59 | {
60 | get
61 | {
62 | Vector3 curr;
63 | _propertySet.TryGetVector3("Target", out curr);
64 | return curr;
65 | }
66 | set
67 | {
68 | _propertySet.InsertVector3("Target", value);
69 | }
70 | }
71 |
72 | ///
73 | /// Distance between the camera and its Target.
74 | ///
75 | public float Radius
76 | {
77 | get
78 | {
79 | float curr;
80 | _propertySet.TryGetScalar("Radius", out curr);
81 | return MathF.Max(200, curr);
82 | }
83 | set
84 | {
85 | _propertySet.InsertScalar("Radius", value);
86 | }
87 | }
88 |
89 | ///
90 | /// The camera's angle of separation from the positive y-axis in radians.
91 | /// From 0 to Pi.
92 | ///
93 | ///
94 | /// When Phi = 0 we are looking down on the "north pole" of the object we are orbiting
95 | /// When Phi = Pi / 2 we are looking at the equator of the object
96 | /// When Phi = Pi we are looking at the "south pole" of the object
97 | /// This mimics spherical coordinates a common spherical coordinate system with (radius, theta, phi)
98 | ///
99 | public float Phi
100 | {
101 | get
102 | {
103 | float epsilon = 0.0001f;
104 | float curr;
105 |
106 | _propertySet.TryGetScalar("Phi", out curr);
107 | return MathF.Min(MathF.PI - epsilon, MathF.Max(epsilon, curr));
108 | }
109 | set
110 | {
111 | float epsilon = 0.0001f;
112 | _propertySet.InsertScalar("Phi", MathF.Min(MathF.PI - epsilon, MathF.Max(epsilon, value)));
113 | }
114 | }
115 |
116 | ///
117 | /// The camera's angle of separation from the positive y-axis in degrees
118 | /// From 0 to 180
119 | ///
120 | ///
121 | /// When PhiInDegrees = 0 we are looking down on the "north pole" of the object we are orbiting
122 | /// When PhiInDegrees = 90 we are looking at the equator of the object
123 | /// When PhiInDegrees = 180 we are looking at the "south pole" of the object
124 | /// This mimics spherical coordinates a common spherical coordinate system with (radius, theta, phi)
125 | ///
126 | public float PhiInDegrees { get => ConvertRadiansToDegrees(Phi); set => Phi = ConvertDegreesToRadians(value); }
127 |
128 | ///
129 | /// The angle of separation from the positive z-axis in radians.
130 | /// Rotates counterclockwise from 0 to 2Pi.
131 | ///
132 | ///
133 | /// When Theta = 0 we are looking at the front of the object we are orbiting
134 | /// When Theta = Pi we are looking at the back of the object
135 | /// When Theta = Pi/2 or 3*Pi/2 we are looking at either the object's left or right side
136 | ///
137 | public float Theta
138 | {
139 | get
140 | {
141 | float curr;
142 | _propertySet.TryGetScalar("Theta", out curr);
143 | return curr;
144 | }
145 | set
146 | {
147 | _propertySet.InsertScalar("Theta", value);
148 | }
149 | }
150 |
151 | ///
152 | /// The angle of separation from the positive z-axis in degrees.
153 | /// Rotates counterclockwise from 0 to 360.
154 | ///
155 | ///
156 | /// When ThetaInDegrees = 0 we are looking at the front of the object we are orbiting
157 | /// When ThetaInDegrees = 180 we are looking at the back of the object
158 | /// When ThetaInDegrees = 90 or 270 we are looking at either the object's left or right side
159 | ///
160 | public float ThetaInDegrees { get => ConvertRadiansToDegrees(Theta); set => Theta = ConvertDegreesToRadians(value); }
161 |
162 | // Helper function that converts radians to degrees
163 | private float ConvertRadiansToDegrees(float rads)
164 | {
165 | return (180 / MathF.PI) * rads;
166 | }
167 |
168 | // Helper function that converts radians to degrees
169 | private float ConvertDegreesToRadians(float degs)
170 | {
171 | return (MathF.PI / 180) * degs;
172 | }
173 |
174 | ///
175 | /// The camera's reference to an object that implements the Projection interace.
176 | /// When setting, this property starts animations on the camera's ModelViewProjectionMatrix property.
177 | ///
178 | /// When set to null, the ModelViewProjectionProperty is animated using an OrthographicProjection with the
179 | /// default values of: Height = 100, Width = 100, Near = 1, Far = 1000.
180 | public Projection Projection { get => _fpCam.Projection; set => _fpCam.Projection = value; }
181 |
182 | ///
183 | /// Returns the camera's position in 3D world space.
184 | ///
185 | /// A Vector3 that represents the camera's extrinsic position in 3D world space.
186 | public Vector3 GetAbsolutePosition()
187 | {
188 | float x = MathF.Sin(Phi) * MathF.Sin(Theta);
189 | float y = -MathF.Cos(Phi);
190 | float z = MathF.Sin(Phi) * MathF.Cos(Theta);
191 |
192 | return Target + (Radius * new Vector3(x, y, z));
193 | }
194 |
195 | ///
196 | /// Returns the camera's position in 3D world space.
197 | ///
198 | ///
199 | public void SetAbsolutePosition(Vector3 value)
200 | {
201 | Radius = Vector3.Distance(Target, value);
202 | Theta = MathF.Atan2(value.X, value.Z);
203 | Phi = MathF.Atan2(value.Z, value.Y);
204 | }
205 |
206 | ///
207 | /// Returns the matrix created from the camera's translation and rotation transformations.
208 | ///
209 | /// A Matrix4x4 that is created from the camera's target, radius, phi, and theta.
210 | public Matrix4x4 GetViewMatrix()
211 | {
212 | Vector3 position = GetAbsolutePosition();
213 |
214 | // use OrbitalCamera's properties to calculate rotaation in terms of yaw, pitch, and roll
215 | Matrix4x4 matPos = Matrix4x4.CreateTranslation(-position);
216 | Matrix4x4 matRoll = Matrix4x4.CreateFromAxisAngle(new Vector3(0, 0, 1), 0);
217 | Matrix4x4 matPitch = Matrix4x4.CreateFromAxisAngle(new Vector3(1, 0, 0), -MathF.Asin(Vector3.Normalize(Target - position).Y));
218 | Matrix4x4 matYaw = Matrix4x4.CreateFromAxisAngle(new Vector3(0, 1, 0), -Theta);
219 |
220 | return matPos * matYaw * matPitch * matRoll;
221 | }
222 |
223 | ///
224 | /// Returns that a matrix created from the camera's view matrix and it's Projection's projection matrix.
225 | ///
226 | /// A Matrix4x4 that is the product of matrices created from the Camera's target, radius, phi, and theta and its Projection's projection matrix.
227 | public Matrix4x4 GetModelViewProjectionMatrix()
228 | {
229 | return GetViewMatrix() * Projection.GetProjectionMatrix();
230 | }
231 |
232 | // Creates expression animations to drive an FPCamera's position and rotation through the OrbitalCamera's phi, theta, and radius
233 | private void StartAnimationsOnFPCamera()
234 | {
235 | CompositionPropertySet fpCamera = _fpCam.GetPropertySet();
236 |
237 | // Drives FPCamera's position based on the following formula
238 | // FPCamera.Position = Radius*( Sin(Phi)*Sin(Theta), -Cos(Phi), Sin(Phi)*Cos(Theta) )
239 | // Sums with Target in the case where Target is not the origin
240 | var positionExpression = _compositor.CreateExpressionAnimation();
241 | positionExpression.Expression =
242 | "OrbitalCamera.Target + OrbitalCamera.Radius * " +
243 | "Vector3(" +
244 | "Sin(Clamp(OrbitalCamera.Phi, epsilon, Pi - epsilon)) * Sin(OrbitalCamera.Theta), " +
245 | "-Cos(Clamp(OrbitalCamera.Phi, epsilon, Pi - epsilon)), " +
246 | "Sin(Clamp(OrbitalCamera.Phi, epsilon, Pi - epsilon)) * Cos(OrbitalCamera.Theta))";
247 | positionExpression.SetExpressionReferenceParameter("OrbitalCamera", _propertySet);
248 | positionExpression.SetScalarParameter("epsilon", 0.0001f);
249 | fpCamera.StartAnimation("Position", positionExpression);
250 |
251 | // Drives FPCamera's yaw by equating it with Theta
252 | var yawExpression = _compositor.CreateExpressionAnimation();
253 | yawExpression.Expression = "OrbitalCamera.Theta";
254 | yawExpression.SetExpressionReferenceParameter("OrbitalCamera", _propertySet);
255 | fpCamera.StartAnimation("Yaw", yawExpression);
256 |
257 | // Drives FPCamera's yaw using the vector eminating from the camera's position to its target
258 | var pitchExpression = _compositor.CreateExpressionAnimation();
259 | pitchExpression.Expression = "Asin(Normalize(OrbitalCamera.Target - FPCamera.Position).Y)";
260 | pitchExpression.SetExpressionReferenceParameter("OrbitalCamera", _propertySet);
261 | pitchExpression.SetExpressionReferenceParameter("FPCamera", fpCamera);
262 | fpCamera.StartAnimation("Pitch", pitchExpression);
263 |
264 | // Links OrbitalCamera's ModelViewProjectionMatrix to the ModelViewProjectionMatrix that's computed in FPCamera
265 | var modelViewProjExpression = _compositor.CreateExpressionAnimation();
266 | modelViewProjExpression.Expression = "FPCamera.ModelViewProjectionMatrix";
267 | modelViewProjExpression.SetReferenceParameter("FPCamera", fpCamera);
268 | _propertySet.StartAnimation("ModelViewProjectionMatrix", modelViewProjExpression);
269 | }
270 |
271 | ///
272 | /// Returns the camera's set of animatable properties.
273 | ///
274 | /// A CompositionPropertySet holding the camera's properties.
275 | public CompositionPropertySet GetPropertySet()
276 | {
277 | return _propertySet;
278 | }
279 |
280 | ///
281 | /// Starts a given animation on the specified property.
282 | ///
283 | /// The name of the property to be animated.
284 | /// The animation being applied.
285 | public void StartAnimation(string propertyName, CompositionAnimation animation)
286 | {
287 | _propertySet.StartAnimation(propertyName, animation);
288 | }
289 |
290 | ///
291 | /// Stops any animations on the specified property.
292 | ///
293 | /// The name of the property whose animations we are stopping.
294 | public void StopAnimation(string propertyName)
295 | {
296 | _propertySet.StopAnimation(propertyName);
297 | }
298 | }
299 | }
--------------------------------------------------------------------------------
/Experimental/CameraComponent/OrthographicProjection.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Numerics;
7 | using Windows.UI.Composition;
8 |
9 | namespace CameraComponent
10 | {
11 | ///
12 | /// A class that defines an orthographic projection with a distance to the near and far planes and a size.
13 | /// Implements the Projection and Animatable interfaces.
14 | ///
15 | public sealed class OrthographicProjection : Projection
16 | {
17 | private CompositionPropertySet _propertySet;
18 | private Compositor _compositor;
19 |
20 | ///
21 | /// Creates a OrthographicProjection with default properties.
22 | /// Size = 100
23 | /// Near = 1
24 | /// Far = 1000
25 | ///
26 | ///
27 | /// Thrown when constructor is passed a null value.
28 | public OrthographicProjection(Compositor compositor)
29 | {
30 | if (compositor == null)
31 | {
32 | throw new System.ArgumentException("Compositor cannot be null");
33 | }
34 |
35 | _compositor = compositor;
36 | _propertySet = _compositor.CreatePropertySet();
37 |
38 | // Create the properties for the projection
39 | _propertySet.InsertScalar("Size", 100f);
40 | _propertySet.InsertScalar("Near", 1f);
41 | _propertySet.InsertScalar("Far", 1000f);
42 | _propertySet.InsertMatrix4x4("ProjectionMatrix", Matrix4x4.Identity);
43 |
44 | StartAnimationsOnProjectionMatrix();
45 | }
46 |
47 | ///
48 | /// Size of the square plane that the image is projected onto.
49 | ///
50 | public float Size
51 | {
52 | get
53 | {
54 | float curr;
55 | _propertySet.TryGetScalar("Size", out curr);
56 | return curr;
57 | }
58 | set
59 | {
60 | float epsilon = 0.0001f;
61 | _propertySet.InsertScalar("Size", MathF.Max(epsilon, value));
62 | }
63 | }
64 |
65 | ///
66 | /// Distance from the eye to the near plane.
67 | ///
68 | public float Near
69 | {
70 | get
71 | {
72 | float curr;
73 | _propertySet.TryGetScalar("Near", out curr);
74 | return curr;
75 | }
76 | set
77 | {
78 | float epsilon = 0.0001f;
79 | _propertySet.InsertScalar("Near", MathF.Max(epsilon, value));
80 | }
81 | }
82 |
83 | ///
84 | /// Distance from the eye to the far plane.
85 | ///
86 | public float Far
87 | {
88 | get
89 | {
90 | float curr;
91 | _propertySet.TryGetScalar("Far", out curr);
92 | return curr;
93 | }
94 | set
95 | {
96 | _propertySet.InsertScalar("Far", value);
97 | }
98 | }
99 |
100 | ///
101 | /// Returns the matrix created from the projection's Near, Far, and Size.
102 | ///
103 | /// A Matrix4x4 that normalizes the scene in the range (-1, -1, -1) to (1, 1, 1).
104 | public Matrix4x4 GetProjectionMatrix()
105 | {
106 | Matrix4x4 matProj = Matrix4x4.Identity;
107 | matProj.M11 = 1 / Size;
108 | matProj.M22 = 1 / Size;
109 | matProj.M33 = 1 / (Far - Near);
110 |
111 | return matProj;
112 | }
113 |
114 | private void StartAnimationsOnProjectionMatrix()
115 | {
116 | var matProj =
117 | "Matrix4x4(" +
118 | "1 / Max(epsilon, OrthoProj.Size), 0, 0, 0, " +
119 | "0, 1 / Max(epsilon, OrthoProj.Size), 0, 0, " +
120 | "0, 0, 1 / (OrthoProj.Far - OrthoProj.Near), 0, " +
121 | "0, 0, 0, 1)";
122 |
123 | var projExpression = _compositor.CreateExpressionAnimation();
124 | projExpression.Expression = matProj;
125 | projExpression.SetScalarParameter("epsilon", 0.0001f);
126 | projExpression.SetReferenceParameter("OrthoProj", _propertySet);
127 |
128 | _propertySet.StartAnimation("ProjectionMatrix", projExpression);
129 | }
130 |
131 | ///
132 | /// Returns the projection's set of animatable properties.
133 | ///
134 | /// A CompositionPropertySet holding the projection's properties.
135 | public CompositionPropertySet GetPropertySet()
136 | {
137 | return _propertySet;
138 | }
139 |
140 | ///
141 | /// Starts a given animation on the specified property.
142 | ///
143 | /// The name of the property to be animated.
144 | /// The animation being applied.
145 | public void StartAnimation(string propertyName, CompositionAnimation animation)
146 | {
147 | _propertySet.StartAnimation(propertyName, animation);
148 | }
149 |
150 | ///
151 | /// Stops any animations on the specified property.
152 | ///
153 | /// The name of the property whose animations we are stopping.
154 | public void StopAnimation(string propertyName)
155 | {
156 | _propertySet.StopAnimation(propertyName);
157 | }
158 | }
159 | }
--------------------------------------------------------------------------------
/Experimental/CameraComponent/PerspectiveProjection.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Numerics;
7 | using Windows.UI.Composition;
8 |
9 | namespace CameraComponent
10 | {
11 | ///
12 | /// A class that defines a perspective projection with a distance to the near and far planes and a field of view.
13 | /// Implements the Projection and Animatable interfaces.
14 | ///
15 | public sealed class PerspectiveProjection : Projection
16 | {
17 | private Compositor _compositor;
18 | private CompositionPropertySet _propertySet;
19 |
20 | ///
21 | /// Creates a PerspectiveProjection with default properties.
22 | /// Fov = Pi / 2
23 | /// Near = 1
24 | /// Far = 1000
25 | ///
26 | ///
27 | /// Thrown when constructor is passed a null value.
28 | public PerspectiveProjection(Compositor compositor)
29 | {
30 | if (compositor == null)
31 | {
32 | throw new System.ArgumentException("Compositor cannot be null");
33 | }
34 |
35 | _compositor = compositor;
36 | _propertySet = _compositor.CreatePropertySet();
37 |
38 | // Create the properties for the projection
39 | _propertySet.InsertScalar("Fov", MathF.PI / 2);
40 | _propertySet.InsertScalar("Near", 1f);
41 | _propertySet.InsertScalar("Far", 1000f);
42 | _propertySet.InsertMatrix4x4("ProjectionMatrix", Matrix4x4.Identity);
43 |
44 | StartAnimationonProjectionMatrix();
45 | }
46 |
47 | ///
48 | /// The field of view of the projection's frustum in radians.
49 | ///
50 | public float Fov
51 | {
52 | get
53 | {
54 | float curr;
55 | _propertySet.TryGetScalar("Fov", out curr);
56 | return curr;
57 | }
58 | set
59 | {
60 | float epsilon = 0.0001f;
61 | _propertySet.InsertScalar("Fov", MathF.Min(MathF.PI - epsilon, MathF.Max(epsilon, value)));
62 | }
63 | }
64 |
65 | ///
66 | /// The field of view of the projection's frustum in degrees.
67 | ///
68 | public float FovInDegrees { get => ConvertRadiansToDegrees(Fov); set => Fov = ConvertDegreesToRadians(value); }
69 |
70 | // Helper function that converts radians to degrees
71 | private float ConvertRadiansToDegrees(float rads)
72 | {
73 | return (180 / MathF.PI) * rads;
74 | }
75 |
76 | // Helper function that converts radians to degrees
77 | private float ConvertDegreesToRadians(float degs)
78 | {
79 | return (MathF.PI / 180) * degs;
80 | }
81 |
82 | ///
83 | /// Distance from the eye to the near plane.
84 | ///
85 | public float Near
86 | {
87 | get
88 | {
89 | float curr;
90 | _propertySet.TryGetScalar("Near", out curr);
91 | return curr;
92 | }
93 | set
94 | {
95 | float epsilon = 0.0001f;
96 | _propertySet.InsertScalar("Near", MathF.Max(epsilon, value));
97 | }
98 | }
99 |
100 | ///
101 | /// Distance from the eye to the far plane.
102 | ///
103 | public float Far
104 | {
105 | get
106 | {
107 | float curr;
108 | _propertySet.TryGetScalar("Far", out curr);
109 | return curr;
110 | }
111 | set
112 | {
113 | _propertySet.InsertScalar("Far", value);
114 | }
115 | }
116 |
117 | ///
118 | /// Returns the matrix created from the projection's Near, Far, and Fov values.
119 | ///
120 | /// A Matrix4x4 that normalizes the scene in the range (-1, -1, -1) to (1, 1, 1).
121 | public Matrix4x4 GetProjectionMatrix()
122 | {
123 | Matrix4x4 matProj = Matrix4x4.Identity;
124 | matProj.M11 = 1 / MathF.Tan(Fov / 2);
125 | matProj.M22 = 1 / MathF.Tan(Fov / 2);
126 | matProj.M33 = (Far - Near) / -(Far + Near);
127 | matProj.M34 = -1;
128 | matProj.M43 = (-2 * Far * Near) / -(Far + Near);
129 |
130 | return matProj;
131 | }
132 |
133 |
134 | ///
135 | /// Returns the projection's set of animatable properties.
136 | ///
137 | /// A CompositionPropertySet holding the projection's properties.
138 | public CompositionPropertySet GetPropertySet()
139 | {
140 | return _propertySet;
141 | }
142 |
143 | private void StartAnimationonProjectionMatrix()
144 | {
145 | var matProj =
146 | "Matrix4x4(" +
147 | "1 / Tan(Clamp(PerspProj.Fov / 2, epsilon, Pi - epsilon)), 0, 0, 0, " +
148 | "0, 1 / Tan(Clamp(PerspProj.Fov / 2, epsilon, Pi - epsilon)), 0, 0, " +
149 | "0, 0, (PerspProj.Far - PerspProj.Near) / -(PerspProj.Far + PerspProj.Near), -1, " +
150 | "0, 0, (-2 * PerspProj.Far * PerspProj.Near) / -(PerspProj.Far + PerspProj.Near), 1)";
151 |
152 | var projExpression = _compositor.CreateExpressionAnimation();
153 | projExpression.Expression = matProj;
154 | projExpression.SetScalarParameter("epsilon", 0.0001f);
155 | projExpression.SetReferenceParameter("PerspProj", _propertySet);
156 |
157 | _propertySet.StartAnimation("ProjectionMatrix", projExpression);
158 | }
159 |
160 | ///
161 | /// Starts a given animation on the specified property.
162 | ///
163 | /// The name of the property to be animated.
164 | /// The animation being applied.
165 | public void StartAnimation(string propertyName, CompositionAnimation animation)
166 | {
167 | _propertySet.StartAnimation(propertyName, animation);
168 | }
169 |
170 | ///
171 | /// Stops any animations on the specified property.
172 | ///
173 | /// The name of the property whose animations we are stopping.
174 | public void StopAnimation(string propertyName)
175 | {
176 | _propertySet.StopAnimation(propertyName);
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/Projection.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Numerics;
6 |
7 | namespace CameraComponent
8 | {
9 | ///
10 | /// An interface that defines properties and functions that a Projection object must implement.
11 | ///
12 | public interface Projection : Animatable
13 | {
14 | ///
15 | /// Distance from the camera to the near plane.
16 | ///
17 | float Near { get; set; }
18 |
19 | ///
20 | /// Distance from the camera to the far plane.
21 | ///
22 | float Far { get; set; }
23 |
24 | ///
25 | /// Returns the matrix created by the near and far planes and other properties of the projection.
26 | ///
27 | /// A Matrix4x4 created from the specific type of projection's properties.
28 | Matrix4x4 GetProjectionMatrix();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Experimental/CameraComponent/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Reflection;
6 | using System.Runtime.CompilerServices;
7 | using System.Runtime.InteropServices;
8 |
9 | // General Information about an assembly is controlled through the following
10 | // set of attributes. Change these attribute values to modify the information
11 | // associated with an assembly.
12 | [assembly: AssemblyTitle("CameraComponent")]
13 | [assembly: AssemblyDescription("")]
14 | [assembly: AssemblyConfiguration("")]
15 | [assembly: AssemblyCompany("")]
16 | [assembly: AssemblyProduct("CameraComponent")]
17 | [assembly: AssemblyCopyright("Copyright © 2019")]
18 | [assembly: AssemblyTrademark("")]
19 | [assembly: AssemblyCulture("")]
20 |
21 | // Version information for an assembly consists of the following four values:
22 | //
23 | // Major Version
24 | // Minor Version
25 | // Build Number
26 | // Revision
27 | //
28 | // You can specify all the values or you can default the Build and Revision Numbers
29 | // by using the '*' as shown below:
30 | // [assembly: AssemblyVersion("1.0.*")]
31 | [assembly: AssemblyVersion("1.0.0.0")]
32 | [assembly: AssemblyFileVersion("1.0.0.0")]
33 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Windows Community Toolkit
2 |
3 | Copyright (c) .NET Foundation and Contributors
4 |
5 | All rights reserved.
6 |
7 | # MIT License (MIT)
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SceneLoader for Windows UI
2 |
3 | SceneLoader is a library for generating [Windows.UI.Composition.Scenes](https://docs.microsoft.com/uwp/api/windows.ui.composition.scenes) scene graphs from 3D file formats such as [glTF](https://www.khronos.org/gltf/). This project aims to simplify the design-to-code workflow for rendering 3D assets in your Windows applications.
4 |
5 | SceneLoader currently produces a [SceneNode](https://docs.microsoft.com/uwp/api/windows.ui.composition.scenes.scenenode), allowing you to programmatically construct your own [Visual](https://docs.microsoft.com/uwp/api/windows.ui.composition.scenes.scenevisual) tree. A [proposed companion Microsoft.UI.Xaml control](https://github.com/microsoft/microsoft-ui-xaml/issues/686) is expected to enable 3D assets to be loaded from markup without requiring explicit management of the Visual tree.
6 |
7 | ## Supported SDKs
8 | * May 2019 Update (18362)
9 |
10 | ## Getting Started
11 | * [Documentation](https://docs.microsoft.com/uwp/api/windows.ui.composition.scenes)
12 | * [Code Sample](https://github.com/windows-toolkit/SceneLoader/blob/master/TestViewer/MainPage.xaml.cs)
13 |
14 | ## Build Status
15 | | Target | Branch | Status | Recommended NuGet package |
16 | | ------ | ------ | ------ | ------ |
17 | | 0.0.1 | master | [](https://dev.azure.com/dotnet/WindowsCommunityToolkit/_build/latest?definitionId=80&branchName=master) | ? |
18 |
19 | ## Feedback and Requests
20 | Please use [GitHub Issues](https://github.com/windows-toolkit/SceneLoader/issues) for bug reports and feature requests.
21 |
22 | ## Principles
23 | This project has adopted the code of conduct defined by the [Contributor Covenant](http://contributor-covenant.org/)
24 | to clarify expected behavior in our community.
25 | For more information see the [.NET Foundation Code of Conduct](http://dotnetfoundation.org/code-of-conduct).
26 |
27 | ## .NET Foundation
28 | This project is supported by the [.NET Foundation](http://dotnetfoundation.org).
29 |
30 |
--------------------------------------------------------------------------------
/SceneLoader.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29123.88
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SceneLoaderComponent", "SceneLoader\SceneLoader.vcxproj", "{88C4D662-8669-433B-8A8B-47B3A17E3C6E}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestViewer", "TestViewer\TestViewer.csproj", "{5D504AFF-651A-4C27-BA19-550663227A85}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraComponent", "Experimental\CameraComponent\CameraComponent.csproj", "{239C87C3-1E17-4F01-8D93-9B21C1A53F3D}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|ARM = Debug|ARM
16 | Debug|ARM64 = Debug|ARM64
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|Any CPU = Release|Any CPU
20 | Release|ARM = Release|ARM
21 | Release|ARM64 = Release|ARM64
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|Any CPU.ActiveCfg = Debug|Win32
27 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|Any CPU.Build.0 = Debug|Win32
28 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|ARM.ActiveCfg = Debug|ARM
29 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|ARM.Build.0 = Debug|ARM
30 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|ARM64.ActiveCfg = Debug|ARM64
31 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|ARM64.Build.0 = Debug|ARM64
32 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|x64.ActiveCfg = Debug|x64
33 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|x64.Build.0 = Debug|x64
34 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|x86.ActiveCfg = Debug|Win32
35 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Debug|x86.Build.0 = Debug|Win32
36 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|Any CPU.ActiveCfg = Release|Win32
37 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|Any CPU.Build.0 = Release|Win32
38 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|ARM.ActiveCfg = Release|ARM
39 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|ARM.Build.0 = Release|ARM
40 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|ARM64.ActiveCfg = Release|ARM64
41 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|ARM64.Build.0 = Release|ARM64
42 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|x64.ActiveCfg = Release|x64
43 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|x64.Build.0 = Release|x64
44 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|x86.ActiveCfg = Release|Win32
45 | {88C4D662-8669-433B-8A8B-47B3A17E3C6E}.Release|x86.Build.0 = Release|Win32
46 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|Any CPU.ActiveCfg = Debug|x86
47 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|Any CPU.Build.0 = Debug|x86
48 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|Any CPU.Deploy.0 = Debug|x86
49 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM.ActiveCfg = Debug|ARM
50 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM.Build.0 = Debug|ARM
51 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM.Deploy.0 = Debug|ARM
52 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM64.ActiveCfg = Debug|ARM64
53 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM64.Build.0 = Debug|ARM64
54 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|ARM64.Deploy.0 = Debug|ARM64
55 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x64.ActiveCfg = Debug|x64
56 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x64.Build.0 = Debug|x64
57 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x64.Deploy.0 = Debug|x64
58 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x86.ActiveCfg = Debug|x86
59 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x86.Build.0 = Debug|x86
60 | {5D504AFF-651A-4C27-BA19-550663227A85}.Debug|x86.Deploy.0 = Debug|x86
61 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|Any CPU.ActiveCfg = Release|x86
62 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|Any CPU.Build.0 = Release|x86
63 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|Any CPU.Deploy.0 = Release|x86
64 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM.ActiveCfg = Release|ARM
65 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM.Build.0 = Release|ARM
66 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM.Deploy.0 = Release|ARM
67 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM64.ActiveCfg = Release|ARM64
68 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM64.Build.0 = Release|ARM64
69 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|ARM64.Deploy.0 = Release|ARM64
70 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x64.ActiveCfg = Release|x64
71 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x64.Build.0 = Release|x64
72 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x64.Deploy.0 = Release|x64
73 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x86.ActiveCfg = Release|x86
74 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x86.Build.0 = Release|x86
75 | {5D504AFF-651A-4C27-BA19-550663227A85}.Release|x86.Deploy.0 = Release|x86
76 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|Any CPU.ActiveCfg = Debug|x86
77 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|Any CPU.Build.0 = Debug|x86
78 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|ARM.ActiveCfg = Debug|ARM
79 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|ARM.Build.0 = Debug|ARM
80 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|ARM64.ActiveCfg = Debug|ARM64
81 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|ARM64.Build.0 = Debug|ARM64
82 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|x64.ActiveCfg = Debug|x64
83 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|x64.Build.0 = Debug|x64
84 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|x86.ActiveCfg = Debug|x86
85 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Debug|x86.Build.0 = Debug|x86
86 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|Any CPU.ActiveCfg = Release|x86
87 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|Any CPU.Build.0 = Release|x86
88 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|ARM.ActiveCfg = Release|ARM
89 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|ARM.Build.0 = Release|ARM
90 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|ARM64.ActiveCfg = Release|ARM64
91 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|ARM64.Build.0 = Release|ARM64
92 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|x64.ActiveCfg = Release|x64
93 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|x64.Build.0 = Release|x64
94 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|x86.ActiveCfg = Release|x86
95 | {239C87C3-1E17-4F01-8D93-9B21C1A53F3D}.Release|x86.Build.0 = Release|x86
96 | EndGlobalSection
97 | GlobalSection(SolutionProperties) = preSolution
98 | HideSolutionNode = FALSE
99 | EndGlobalSection
100 | GlobalSection(ExtensibilityGlobals) = postSolution
101 | SolutionGuid = {79558D4B-E776-4662-A741-BBDDC6C0556F}
102 | EndGlobalSection
103 | EndGlobal
104 |
--------------------------------------------------------------------------------
/SceneLoader/Bounds3D.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "Bounds3D.h"
8 |
9 | using namespace std;
10 |
11 | namespace winrt {
12 | using namespace Windows::Foundation::Numerics;
13 | using namespace Windows::UI::Composition::Scenes;
14 | }
15 | using namespace winrt;
16 |
17 | namespace SceneLoader
18 | {
19 | Bounds3D::Bounds3D(SceneBoundingBox sceneBounds)
20 | {
21 | m_min = sceneBounds.Min();
22 | m_max = sceneBounds.Max();
23 | }
24 |
25 | Bounds3D::Bounds3D(float3 _min, float3 _max)
26 | {
27 | m_min = _min;
28 | m_max = _max;
29 | }
30 |
31 | Bounds3D
32 | Bounds3D::Union(const Bounds3D &lBounds, const Bounds3D &rBounds)
33 | {
34 | winrt::Windows::Foundation::Numerics::float3 newMin;
35 | winrt::Windows::Foundation::Numerics::float3 newMax;
36 |
37 | newMin.x = min(lBounds.Min().x, rBounds.Min().x);
38 | newMin.y = min(lBounds.Min().y, rBounds.Min().y);
39 | newMin.z = min(lBounds.Min().z, rBounds.Min().z);
40 |
41 | newMax.x = max(lBounds.Max().x, rBounds.Max().x);
42 | newMax.y = max(lBounds.Max().y, rBounds.Max().y);
43 | newMax.z = max(lBounds.Max().z, rBounds.Max().z);
44 |
45 | return Bounds3D(newMin, newMax);
46 | }
47 |
48 | Bounds3D
49 | Bounds3D::Transform(const Bounds3D &srcBounds, const winrt::Windows::Foundation::Numerics::float4x4 &srcToDestTransform)
50 | {
51 | float3 newMin(FLT_MAX, FLT_MAX, FLT_MAX);
52 | float3 newMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
53 |
54 | {
55 | float3 boxVertices[8];
56 |
57 | // Setup a cube, first 4 verties will be min (z) plane, 2nd 4 vertices will be max (z) plane
58 | // First vertex in each plane will be at min (x,y) winding clockwise around to rest at (xMax, yMin)
59 |
60 | boxVertices[0] = srcBounds.Min();
61 | boxVertices[6] = srcBounds.Max();
62 |
63 | boxVertices[1] = boxVertices[0];
64 | boxVertices[1].y = boxVertices[6].y;
65 |
66 | boxVertices[2] = boxVertices[1];
67 | boxVertices[2].x = boxVertices[6].x;
68 |
69 | boxVertices[3] = boxVertices[2];
70 | boxVertices[3].y = boxVertices[0].y;
71 |
72 | boxVertices[4] = boxVertices[0];
73 | boxVertices[4].z = boxVertices[6].z;
74 |
75 | boxVertices[5] = boxVertices[4];
76 | boxVertices[5].y = boxVertices[6].y;
77 |
78 | boxVertices[7] = boxVertices[6];
79 | boxVertices[7].y = boxVertices[0].y;
80 |
81 | for (int i = 0; i < 8; i++)
82 | {
83 | boxVertices[i] = transform(boxVertices[i], srcToDestTransform);
84 |
85 | newMin.x = min(newMin.x, boxVertices[i].x);
86 | newMin.y = min(newMin.y, boxVertices[i].y);
87 | newMin.z = min(newMin.z, boxVertices[i].z);
88 |
89 | newMax.x = max(newMax.x, boxVertices[i].x);
90 | newMax.y = max(newMax.y, boxVertices[i].y);
91 | newMax.z = max(newMax.z, boxVertices[i].z);
92 | }
93 | }
94 |
95 | return Bounds3D(newMin, newMax);
96 | }
97 |
98 |
99 | float3 Bounds3D::Min() const
100 | {
101 | return m_min;
102 | }
103 |
104 | float3 Bounds3D::Max() const
105 | {
106 | return m_max;
107 | }
108 |
109 |
110 | Bounds3D ComputeTreeBounds(winrt::Windows::UI::Composition::Scenes::SceneNode root);
111 |
112 | void DecomposeMatrix(
113 | const std::array matrix,
114 | winrt::Windows::Foundation::Numerics::float3* pOutScale,
115 | winrt::Windows::Foundation::Numerics::quaternion* pOutRotation,
116 | winrt::Windows::Foundation::Numerics::float3* pOutTranslation
117 | );
118 |
119 | Bounds3D ComputeTreeBounds(
120 | SceneNode root,
121 | float4x4 parentToWorldTransform
122 | )
123 | {
124 | Bounds3D retBounds;
125 |
126 | float4x4 localToWorldTransform = parentToWorldTransform;
127 |
128 | localToWorldTransform *= make_float4x4_scale(root.Transform().Scale());
129 | localToWorldTransform *= make_float4x4_from_quaternion(root.Transform().Orientation());
130 | localToWorldTransform *= make_float4x4_translation(root.Transform().Translation());
131 |
132 | // Check if we have a mesh attached
133 | auto firstComponent = root.Components().First();
134 |
135 | if (firstComponent && firstComponent.HasCurrent())
136 | {
137 | auto meshRenderer = firstComponent.Current().as();
138 |
139 | if (meshRenderer)
140 | {
141 | auto mesh = meshRenderer.Mesh();
142 |
143 | if (mesh)
144 | {
145 | Bounds3D localBounds = mesh.Bounds();
146 |
147 | retBounds = Bounds3D::Transform(localBounds, localToWorldTransform);
148 | }
149 | }
150 | }
151 |
152 | for (UINT i = 0; i < root.Children().Size(); i++)
153 | {
154 | retBounds = Bounds3D::Union(retBounds, ComputeTreeBounds(root.Children().GetAt(i), localToWorldTransform));
155 | }
156 |
157 | return retBounds;
158 | }
159 |
160 | void DecomposeMatrix(
161 | const std::array matrix,
162 | float3* pOutScale,
163 | quaternion* pOutRotation,
164 | float3* pOutTranslation)
165 | {
166 | float4x4 inputMatrix(
167 | matrix[0], matrix[1], matrix[2], matrix[3],
168 | matrix[4], matrix[5], matrix[6], matrix[7],
169 | matrix[8], matrix[9], matrix[10], matrix[11],
170 | matrix[12], matrix[13], matrix[14], matrix[15]
171 | );
172 |
173 | bool fDecomposeResult = decompose(
174 | inputMatrix,
175 | pOutScale,
176 | pOutRotation,
177 | pOutTranslation);
178 |
179 | assert(fDecomposeResult);
180 | }
181 | } // namespace SceneLoader
--------------------------------------------------------------------------------
/SceneLoader/Bounds3D.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 | namespace SceneLoader {
8 |
9 | class Bounds3D
10 | {
11 | public:
12 | Bounds3D(winrt::Windows::UI::Composition::Scenes::SceneBoundingBox sceneBounds);
13 |
14 | Bounds3D(winrt::Windows::Foundation::Numerics::float3 _min = winrt::Windows::Foundation::Numerics::float3(FLT_MAX, FLT_MAX, FLT_MAX),
15 | winrt::Windows::Foundation::Numerics::float3 _max = winrt::Windows::Foundation::Numerics::float3(FLT_MIN, FLT_MIN, FLT_MIN));
16 |
17 | static Bounds3D Union(const Bounds3D &lBounds, const Bounds3D &rBounds);
18 | static Bounds3D Transform(const Bounds3D &srcBounds, const winrt::Windows::Foundation::Numerics::float4x4 &transform);
19 |
20 | winrt::Windows::Foundation::Numerics::float3 Min() const;
21 |
22 | winrt::Windows::Foundation::Numerics::float3 Max() const;
23 |
24 | private:
25 | winrt::Windows::Foundation::Numerics::float3 m_min;
26 | winrt::Windows::Foundation::Numerics::float3 m_max;
27 | };
28 |
29 | Bounds3D ComputeTreeBounds(winrt::Windows::UI::Composition::Scenes::SceneNode root,
30 | winrt::Windows::Foundation::Numerics::float4x4 parentTransform);
31 |
32 | void DecomposeMatrix(
33 | const std::array matrix,
34 | winrt::Windows::Foundation::Numerics::float3* pOutScale,
35 | winrt::Windows::Foundation::Numerics::quaternion* pOutRotation,
36 | winrt::Windows::Foundation::Numerics::float3* pOutTranslation
37 | );
38 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "UtilForIntermingledNamespaces.h"
8 | #include "GLTFVisitor.h"
9 |
10 | using namespace std;
11 | using namespace Microsoft::glTF;
12 |
13 | namespace winrt {
14 | using namespace Windows::UI::Composition;
15 | using namespace Windows::UI::Composition::Scenes;
16 | }
17 | using namespace winrt;
18 |
19 | extern std::wstringstream s_export;
20 |
21 | namespace SceneLoader
22 | {
23 | GLTFVisitor::GLTFVisitor(Compositor compositor,
24 | SceneNode rootSceneNode,
25 | shared_ptr resourceSet,
26 | shared_ptr gltfResourceReader,
27 | Document& gltfDocument,
28 | Scene& gltfScene) :
29 | m_compositor(compositor),
30 | m_rootSceneNode(rootSceneNode),
31 | m_sceneNodeMap(single_threaded_map()),
32 | m_resourceSet(resourceSet),
33 | m_gltfResourceReader(gltfResourceReader),
34 | m_gltfDocument(gltfDocument),
35 | m_gltfScene(gltfScene)
36 | {
37 | }
38 |
39 | HRESULT GLTFVisitor::EnsureGraphicsDevice()
40 | {
41 | HRESULT hr = S_OK;
42 |
43 | if (!m_graphicsDevice)
44 | {
45 | // Initialize DX
46 | winrt::com_ptr cpDevice;
47 | winrt::com_ptr cpContext;
48 | UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
49 | D3D_FEATURE_LEVEL featureLevels[] =
50 | {
51 | D3D_FEATURE_LEVEL_11_1,
52 | D3D_FEATURE_LEVEL_11_0,
53 | D3D_FEATURE_LEVEL_10_1,
54 | D3D_FEATURE_LEVEL_10_0,
55 | D3D_FEATURE_LEVEL_9_3,
56 | D3D_FEATURE_LEVEL_9_2,
57 | D3D_FEATURE_LEVEL_9_1
58 | };
59 | D3D_FEATURE_LEVEL usedFeatureLevel;
60 |
61 | hr = D3D11CreateDevice(
62 | nullptr,
63 | D3D_DRIVER_TYPE_HARDWARE,
64 | nullptr,
65 | creationFlags,
66 | featureLevels,
67 | ARRAYSIZE(featureLevels),
68 | D3D11_SDK_VERSION,
69 | cpDevice.put(),
70 | &usedFeatureLevel,
71 | cpContext.put());
72 |
73 | winrt::com_ptr cpD2DFactory;
74 | winrt::com_ptr cpD2D1Device;
75 | winrt::com_ptr cpd3dDevice = cpDevice.as();
76 | hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), cpD2DFactory.put_void());
77 | winrt::com_ptr cpDxgiDevice = cpd3dDevice.as();
78 | cpD2DFactory->CreateDevice(cpDxgiDevice.get(), cpD2D1Device.put());
79 |
80 | winrt::com_ptr cpCompositorInterop = m_compositor.as< ABI::Windows::UI::Composition::ICompositorInterop>();
81 | cpCompositorInterop->CreateGraphicsDevice(/*cpDevice*/cpD2D1Device.get(), m_graphicsDevice.put());
82 |
83 | assert(m_graphicsDevice);
84 | }
85 |
86 | return hr;
87 | }
88 |
89 | winrt::Windows::UI::Composition::CompositionMipmapSurface
90 | GLTFVisitor::EnsureMipMapSurfaceId(
91 | const std::string id,
92 | winrt::Windows::Graphics::SizeInt32 sizePixels,
93 | winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
94 | winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode)
95 | {
96 | EnsureGraphicsDevice();
97 |
98 | winrt::Windows::UI::Composition::ICompositionGraphicsDevice3 cpGraphicsDevice3 = m_graphicsDevice.as< winrt::Windows::UI::Composition::ICompositionGraphicsDevice3>();
99 |
100 | return m_resourceSet->EnsureMipMapSurfaceId(
101 | id,
102 | sizePixels,
103 | pixelFormat,
104 | alphaMode,
105 | cpGraphicsDevice3
106 | );
107 | }
108 |
109 |
110 | } // SceneLoader
111 |
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 | #include "SceneResourceSet.h"
8 |
9 | namespace SceneLoader
10 | {
11 | struct GLTFVisitor
12 | {
13 | GLTFVisitor(winrt::Windows::UI::Composition::Compositor compositor,
14 | winrt::Windows::UI::Composition::Scenes::SceneNode rootSceneNode,
15 | std::shared_ptr resourceSet,
16 | std::shared_ptr gltfResourceReader,
17 | Microsoft::glTF::Document& gltfDocument,
18 | Microsoft::glTF::Scene& gltfScene);
19 |
20 | // Node
21 | void operator()(const Microsoft::glTF::Node& node, const Microsoft::glTF::Node* nodeParent);
22 |
23 | // Mesh
24 | void operator()(const Microsoft::glTF::Mesh& mesh, Microsoft::glTF::VisitState alreadyVisited);
25 |
26 | // MeshPrimitive
27 | void operator()(const Microsoft::glTF::MeshPrimitive&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
28 |
29 | // Material
30 | void operator()(const Microsoft::glTF::Material&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
31 |
32 | // Texture
33 | void operator()(const Microsoft::glTF::Texture&, Microsoft::glTF::TextureType, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
34 |
35 | // Image
36 | void operator()(const Microsoft::glTF::Image&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
37 |
38 | // Sampler
39 | void operator()(const Microsoft::glTF::Sampler&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
40 |
41 | // Skin
42 | void operator()(const Microsoft::glTF::Skin&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
43 |
44 | // Camera
45 | void operator()(const Microsoft::glTF::Camera&, Microsoft::glTF::VisitState, const Microsoft::glTF::VisitDefaultAction&);
46 |
47 | HRESULT EnsureGraphicsDevice();
48 |
49 |
50 | winrt::Windows::UI::Composition::CompositionMipmapSurface EnsureMipMapSurfaceId(
51 | const std::string id,
52 | winrt::Windows::Graphics::SizeInt32 size,
53 | winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
54 | winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode);
55 |
56 | private:
57 | winrt::Windows::UI::Composition::Compositor m_compositor{ nullptr };
58 |
59 | winrt::com_ptr m_graphicsDevice{ nullptr };
60 |
61 | // The SceneNode connected to the SceneVisual
62 | winrt::Windows::UI::Composition::Scenes::SceneNode m_rootSceneNode{ nullptr };
63 |
64 | // Only keeps track of the equivalent SceneNodes from the DOM into the Scenes API.
65 | winrt::Windows::Foundation::Collections::IMap m_sceneNodeMap{ nullptr };
66 |
67 | // It keeps the equivalent SceneNodes from the DOM and the ones needed for adapting Mesh and MeshPrimitives into the Scenes API.
68 | winrt::Windows::UI::Composition::Scenes::SceneNode m_latestSceneNode{ nullptr };
69 |
70 | Microsoft::glTF::Document& m_gltfDocument;
71 |
72 | Microsoft::glTF::Scene& m_gltfScene;
73 |
74 | std::shared_ptr m_gltfResourceReader;
75 | std::shared_ptr m_resourceSet;
76 | };
77 | } // SceneLoader
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Camera.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | namespace winrt {
12 | using namespace Windows::UI::Composition;
13 | using namespace Windows::UI::Composition::Scenes;
14 | }
15 | using namespace winrt;
16 |
17 | namespace SceneLoader
18 | {
19 | // Camera
20 | void GLTFVisitor::operator()(const Camera& /*camera*/, VisitState /*alreadyVisited*/, const VisitDefaultAction&)
21 | {
22 | }
23 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Image.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 | #include "wincodec.h"
9 |
10 | using namespace std;
11 | using namespace Microsoft::glTF;
12 |
13 | namespace winrt {
14 | using namespace Windows::Graphics;
15 | using namespace Windows::Graphics::DirectX;
16 | using namespace Windows::UI::Composition;
17 | }
18 | using namespace winrt;
19 |
20 | namespace SceneLoader
21 | {
22 | // Image
23 | void GLTFVisitor::operator()(const Image& image, VisitState alreadyVisited, const VisitDefaultAction&)
24 | {
25 | if (alreadyVisited == VisitState::New)
26 | {
27 | std::vector imageData = m_gltfResourceReader->ReadBinaryData(m_gltfDocument, image);
28 |
29 | const void* pSource = static_cast(imageData.data());
30 |
31 | // Create input stream for memory
32 | com_ptr cpWIC;
33 | winrt::check_hresult(CoCreateInstance(
34 | CLSID_WICImagingFactory,
35 | NULL,
36 | CLSCTX_INPROC_SERVER,
37 | __uuidof(cpWIC),
38 | (LPVOID*)&cpWIC));
39 |
40 | com_ptr cpStream;
41 | winrt::check_hresult(cpWIC->CreateStream(cpStream.put()));
42 | winrt::check_hresult(cpStream->InitializeFromMemory(static_cast(const_cast(pSource)),
43 | static_cast(imageData.size())));
44 |
45 | com_ptr cpDecoder;
46 | winrt::check_hresult(cpWIC->CreateDecoderFromStream(cpStream.get(), nullptr, WICDecodeMetadataCacheOnDemand, cpDecoder.put()));
47 |
48 | com_ptr cpSource;
49 | winrt::check_hresult(cpDecoder->GetFrame(0, cpSource.put()));
50 |
51 | UINT imageWidth = 0;
52 | UINT imageHeight = 0;
53 | winrt::check_hresult(cpSource->GetSize(&imageWidth, &imageHeight));
54 | SizeInt32 size{ static_cast(imageWidth), static_cast(imageHeight) }; // FIXME: conversion from 'UINT' to 'int32_t' requires a narrowing conversion
55 | DirectXPixelFormat pixelFormat = DirectXPixelFormat::B8G8R8A8UIntNormalized; // Warning: SceneResourceSet::EnsureMipMapSurfaceId hard codes these values
56 | DirectXAlphaMode alphaMode = DirectXAlphaMode::Premultiplied; // Warning: SceneResourceSet::EnsureMipMapSurfaceId hard codes these values
57 |
58 | CompositionMipmapSurface mipmap = EnsureMipMapSurfaceId(
59 | image.id,
60 | size,
61 | pixelFormat,
62 | alphaMode
63 | );
64 |
65 | com_ptr cpCurrentSourceBitmap;
66 |
67 | // Create highest resolution source bitmap
68 | {
69 | com_ptr cpD2DContext;
70 |
71 | // Create Scalar
72 | com_ptr cpScaler;
73 | winrt::check_hresult(cpWIC->CreateBitmapScaler(cpScaler.put()));
74 |
75 | winrt::check_hresult(cpScaler->Initialize(
76 | cpSource.get(), // Bitmap source to scale.
77 | imageWidth, // Scale width to half of original.
78 | imageHeight, // Scale height to half of original.
79 | WICBitmapInterpolationModeFant)); // Use Fant mode interpolation.
80 |
81 | com_ptr cpConverter;
82 |
83 | winrt::check_hresult(cpWIC->CreateFormatConverter(cpConverter.put()));
84 | winrt::check_hresult(cpConverter->Initialize(
85 | cpScaler.get(),
86 | /*WicPixelFormatFromDirectXPixelFormat(pixelFormat, alphaMode)*/GUID_WICPixelFormat32bppPBGRA,
87 | WICBitmapDitherTypeNone,
88 | nullptr,
89 | 0.0f,
90 | WICBitmapPaletteTypeMedianCut));
91 |
92 | CompositionDrawingSurface cpDrawingSurface = mipmap.GetDrawingSurfaceForLevel(0);
93 | com_ptr cpDrawingSurfaceInterop = cpDrawingSurface.as();
94 |
95 | POINT surfaceUpdateOffset;
96 | winrt::check_hresult(cpDrawingSurfaceInterop->BeginDraw(
97 | nullptr,
98 | IID_PPV_ARGS(cpD2DContext.put()),
99 | &surfaceUpdateOffset));
100 |
101 | com_ptr cpCompatibleRenderTarget;
102 | winrt::check_hresult(cpD2DContext->CreateCompatibleRenderTarget(cpCompatibleRenderTarget.put()));
103 |
104 | winrt::check_hresult(cpCompatibleRenderTarget->CreateBitmapFromWicBitmap(
105 | cpConverter.get(),
106 | nullptr,
107 | cpCurrentSourceBitmap.put()));
108 |
109 | winrt::check_hresult(cpDrawingSurfaceInterop->EndDraw());
110 | }
111 |
112 | float sourceBitmapDpiX, sourceBitmapDpiY;
113 |
114 | cpCurrentSourceBitmap->GetDpi(&sourceBitmapDpiX, &sourceBitmapDpiY);
115 |
116 | for (UINT i = 0; i < mipmap.LevelCount(); ++i)
117 | {
118 | CompositionDrawingSurface cpDrawingSurface = mipmap.GetDrawingSurfaceForLevel(i);
119 | com_ptr cpDrawingSurfaceInterop = cpDrawingSurface.as();
120 | com_ptr cpD2DContext;
121 |
122 | #ifndef NDEBUG
123 | {
124 | D2D1_SIZE_U sourceSize2 = cpCurrentSourceBitmap->GetPixelSize();
125 |
126 | assert(sourceSize2.width == imageWidth);
127 | assert(sourceSize2.height == imageHeight);
128 | }
129 | #endif
130 |
131 | POINT surfaceUpdateOffset;
132 | winrt::check_hresult(cpDrawingSurfaceInterop->BeginDraw(
133 | nullptr,
134 | IID_PPV_ARGS(cpD2DContext.put()),
135 | &surfaceUpdateOffset));
136 |
137 | D2D1_RECT_F destRect;
138 | destRect.left = (float)surfaceUpdateOffset.x;
139 | destRect.top = (float)surfaceUpdateOffset.y;
140 | destRect.right = (float)(destRect.left + imageWidth);
141 | destRect.bottom = (float)(destRect.top + imageHeight);
142 |
143 | cpD2DContext->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
144 |
145 | cpD2DContext->DrawBitmap(
146 | cpCurrentSourceBitmap.get(),
147 | &destRect,
148 | 1.0f,
149 | D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
150 | );
151 |
152 | // For debugging, turn this on to clobber the contents with red
153 | #if 0
154 | com_ptr cpSolidColorBrush;
155 | winrt::check_hresult(cpD2DContext->CreateSolidColorBrush(D2D1::ColorF::ColorF(1.0f, 0.0f, 0.0f), cpSolidColorBrush.put()));
156 |
157 | cpD2DContext->FillRectangle(
158 | &destRect,
159 | cpSolidColorBrush.get()
160 | );
161 | #endif
162 |
163 | winrt::check_hresult(cpD2DContext->Flush());
164 |
165 | winrt::check_hresult(cpDrawingSurfaceInterop->EndDraw());
166 |
167 | // Update image size
168 | #undef max
169 | imageWidth = std::max(imageWidth / 2, 1U);
170 | imageHeight = std::max(imageHeight / 2, 1U);
171 |
172 | // Now we need to generate the next level source bitmap that's going to be used for
173 | // the next imagewidth/height. Note that imageWidth/Height have already been divided
174 | // by 2.
175 | com_ptr cpNewD2DTarget;
176 |
177 | D2D1_SIZE_F newDesiredSizeF = D2D1::SizeF(static_cast(imageWidth) / sourceBitmapDpiX, static_cast(imageHeight) / sourceBitmapDpiY);
178 |
179 | // Compatible Target should match format
180 | winrt::check_hresult(cpD2DContext->CreateCompatibleRenderTarget(
181 | newDesiredSizeF,
182 | D2D1::SizeU(imageWidth, imageHeight),
183 | cpCurrentSourceBitmap->GetPixelFormat(),
184 | D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE,
185 | cpNewD2DTarget.put()
186 | ));
187 |
188 | cpNewD2DTarget->BeginDraw();
189 |
190 | cpNewD2DTarget->DrawBitmap(
191 | cpCurrentSourceBitmap.get(),
192 | D2D1::RectF(0.0f, 0.0f, newDesiredSizeF.width, newDesiredSizeF.height),
193 | 1.0f,
194 | D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
195 | );
196 |
197 | winrt::check_hresult(cpNewD2DTarget->Flush());
198 |
199 | winrt::check_hresult(cpNewD2DTarget->EndDraw());
200 |
201 | com_ptr cpNewBitmap;
202 | winrt::check_hresult(cpNewD2DTarget->GetBitmap(cpNewBitmap.put()));
203 |
204 | // Now that we've generated the next level of bitmap, replace our current one
205 | cpCurrentSourceBitmap = cpNewBitmap;
206 | }
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Material.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | namespace winrt {
12 | using namespace Windows::UI::Composition::Scenes;
13 | }
14 | using namespace winrt;
15 |
16 | namespace SceneLoader
17 | {
18 | // Material
19 | void GLTFVisitor::operator()(const Material& material, VisitState /*alreadyVisited*/, const VisitDefaultAction&)
20 | {
21 | auto curMaterial = m_resourceSet->EnsureMaterialById(material.id);
22 |
23 | if (!m_resourceSet->GetGLTFMaterialById(material.id, nullptr))
24 | {
25 | m_resourceSet->StoreGLTFMaterialById(material.id, material);
26 | }
27 | else
28 | {
29 | Microsoft::glTF::Material storedMaterial;
30 |
31 | m_resourceSet->GetGLTFMaterialById(material.id, &storedMaterial);
32 |
33 | assert(storedMaterial == material);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Mesh.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | namespace winrt {
12 | using namespace Windows::UI::Composition::Scenes;
13 | }
14 | using namespace winrt;
15 | using namespace std;
16 |
17 | namespace SceneLoader
18 | {
19 | // Mesh
20 | void GLTFVisitor::operator()(const Mesh& mesh, VisitState state)
21 | {
22 | if (state == VisitState::New)
23 | {
24 | wstring meshID{ mesh.id.begin(), mesh.id.end() };
25 |
26 | // We'll have a new SceneNode for each GLTF Mesh and another for each GLTF MeshComponent.
27 | auto sceneNodeForTheGLTFMesh = SceneNode::Create(m_compositor);
28 | sceneNodeForTheGLTFMesh.Comment(meshID);
29 |
30 | m_latestSceneNode.Children().Append(sceneNodeForTheGLTFMesh);
31 |
32 | m_latestSceneNode = sceneNodeForTheGLTFMesh;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_MeshPrimitive.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "UtilForIntermingledNamespaces.h"
8 | #include "GLTFVisitor.h"
9 |
10 | using namespace std;
11 | using namespace Microsoft::glTF;
12 |
13 | namespace winrt {
14 | using namespace Windows::Foundation::Numerics;
15 | using namespace Windows::Graphics::DirectX;
16 | using namespace Windows::UI::Composition::Scenes;
17 | }
18 | using namespace winrt;
19 |
20 | extern vector s_binExportVector;
21 |
22 | namespace SceneLoader
23 | {
24 | // Mesh Primitive
25 | void GLTFVisitor::operator()(const MeshPrimitive& meshPrimitive, VisitState state, const VisitDefaultAction&) // FIXME: It is creating necessary mesh primitives (engine.gltf)
26 | {
27 | if (state == VisitState::New)
28 | {
29 | static uint16_t sCounter = 0;
30 |
31 | auto sceneNodeForTheGLTFMeshPrimitive = SceneNode::Create(m_compositor);
32 |
33 | // m_latestSceneNode is sceneNodeForTheGLTFMesh
34 | m_latestSceneNode.Children().Append(sceneNodeForTheGLTFMeshPrimitive);
35 |
36 |
37 | // We want all MeshPrimitives of a Mesh to be siblings.
38 | // That's why we don't define m_latestSceneNode as sceneNodeForTheGLTFMeshPrimitive.
39 |
40 | auto curMaterial = m_resourceSet->EnsureMaterialById(meshPrimitive.materialId);
41 |
42 | auto mesh = SceneMesh::Create(m_compositor);
43 |
44 | if (meshPrimitive.mode == MESH_TRIANGLES)
45 | {
46 | mesh.PrimitiveTopology(DirectXPrimitiveTopology::TriangleList);
47 | }
48 | else
49 | {
50 | SceneResourceSet::UnimplementedFeatureFound();
51 | }
52 |
53 | for (auto value : meshPrimitive.attributes)
54 | {
55 | if (value.first == ACCESSOR_POSITION)
56 | {
57 | auto accessorId = meshPrimitive.GetAttributeAccessorId(value.first);
58 | auto& accessor = m_gltfDocument.accessors[accessorId];
59 |
60 | auto data = MeshPrimitiveUtils::GetPositions(m_gltfDocument, *m_gltfResourceReader, accessor);
61 |
62 | mesh.FillMeshAttribute(
63 | SceneAttributeSemantic::Vertex,
64 | DirectXPixelFormat::R32G32B32Float,
65 | CopyArrayOfBytesToMemoryBuffer((BYTE*)data.data(), data.size() * sizeof(float)));
66 | }
67 | else if (value.first == ACCESSOR_NORMAL)
68 | {
69 | auto accessorId = meshPrimitive.GetAttributeAccessorId(value.first);
70 | auto& accessor = m_gltfDocument.accessors[accessorId];
71 | auto data = MeshPrimitiveUtils::GetNormals(m_gltfDocument, *m_gltfResourceReader, accessor);
72 |
73 | mesh.FillMeshAttribute(
74 | SceneAttributeSemantic::Normal,
75 | DirectXPixelFormat::R32G32B32Float,
76 | CopyArrayOfBytesToMemoryBuffer((BYTE*)data.data(), data.size() * sizeof(float)));
77 | }
78 | else if (value.first == ACCESSOR_TANGENT)
79 | {
80 | auto accessorId = meshPrimitive.GetAttributeAccessorId(value.first);
81 | auto& accessor = m_gltfDocument.accessors[accessorId];
82 | auto data = MeshPrimitiveUtils::GetTangents(m_gltfDocument, *m_gltfResourceReader, accessor);
83 |
84 | mesh.FillMeshAttribute(
85 | SceneAttributeSemantic::Tangent,
86 | DirectXPixelFormat::R32G32B32A32Float,
87 | CopyArrayOfBytesToMemoryBuffer((BYTE*)data.data(), data.size() * sizeof(float)));
88 | }
89 | else if ((value.first == ACCESSOR_TEXCOORD_0) || (value.first == ACCESSOR_TEXCOORD_1))
90 | {
91 | auto accessorId = meshPrimitive.GetAttributeAccessorId(value.first);
92 | auto& accessor = m_gltfDocument.accessors[accessorId];
93 | auto data = MeshPrimitiveUtils::GetTexCoords(m_gltfDocument, *m_gltfResourceReader, accessor);
94 |
95 | mesh.FillMeshAttribute(
96 | (value.first == ACCESSOR_TEXCOORD_0) ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1,
97 | DirectXPixelFormat::R32G32Float,
98 | CopyArrayOfBytesToMemoryBuffer((BYTE*)data.data(), data.size() * sizeof(float)));
99 | }
100 | else if (value.first == ACCESSOR_COLOR_0)
101 | {
102 | auto accessorId = meshPrimitive.GetAttributeAccessorId(value.first);
103 | auto& accessor = m_gltfDocument.accessors[accessorId];
104 | auto data = MeshPrimitiveUtils::GetColors(m_gltfDocument, *m_gltfResourceReader, accessor);
105 |
106 | mesh.FillMeshAttribute(
107 | SceneAttributeSemantic::Color,
108 | DirectXPixelFormat::R32UInt,
109 | CopyArrayOfBytesToMemoryBuffer((BYTE*)data.data(), data.size() * sizeof(uint32_t)));
110 | }
111 | } // for attributes
112 |
113 | auto indices = MeshPrimitiveUtils::GetTriangulatedIndices16(m_gltfDocument, *m_gltfResourceReader, meshPrimitive);
114 |
115 | mesh.FillMeshAttribute(
116 | SceneAttributeSemantic::Index,
117 | DirectXPixelFormat::R16UInt,
118 | CopyArrayOfBytesToMemoryBuffer((BYTE*)indices.data(), indices.size() * sizeof(uint16_t)));
119 |
120 | //
121 | // Creates SceneRendererComponent, attaches MeshRenderer and add as component of the SceneNode
122 | //
123 | auto renderComponent = SceneMeshRendererComponent::Create(m_compositor);
124 |
125 | renderComponent.Mesh(mesh);
126 |
127 | renderComponent.Material(curMaterial);
128 |
129 | sceneNodeForTheGLTFMeshPrimitive.Components().Append(renderComponent);
130 |
131 | sCounter++;
132 | m_resourceSet->SetLatestMeshRendererComponent(renderComponent);
133 | }
134 | }
135 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Node.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 | #include "UtilForIntermingledNamespaces.h"
9 | #include "Bounds3D.h"
10 |
11 | using namespace Microsoft::glTF;
12 |
13 | namespace winrt {
14 | using namespace Windows::UI::Composition::Scenes;
15 | using namespace Windows::Foundation::Numerics;
16 | }
17 | using namespace winrt;
18 |
19 | using namespace std;
20 |
21 | namespace SceneLoader
22 | {
23 | // Node
24 | void GLTFVisitor::operator()(const Node& node, const Node* nodeParent)
25 | {
26 | wstring nodeID{ node.id.begin(), node.id.end() };
27 |
28 | auto sceneNode = SceneNode::Create(m_compositor);
29 | sceneNode.Comment(nodeID);
30 |
31 | m_latestSceneNode = sceneNode;
32 | m_sceneNodeMap.Insert(GetHSTRINGFromStdString(node.id), sceneNode);
33 |
34 | if (!nodeParent)
35 | {
36 | m_rootSceneNode.Children().Append(sceneNode);
37 | }
38 | else
39 | {
40 | m_sceneNodeMap.Lookup(GetHSTRINGFromStdString(nodeParent->id)).Children().Append(sceneNode);
41 | }
42 |
43 | switch (node.GetTransformationType())
44 | {
45 | case TRANSFORMATION_MATRIX:
46 | float3 scale;
47 | quaternion rotation;
48 | float3 translation;
49 |
50 | DecomposeMatrix(
51 | node.matrix.values,
52 | &scale,
53 | &rotation,
54 | &translation);
55 |
56 | sceneNode.Transform().Scale(scale);
57 | sceneNode.Transform().Translation(translation);
58 | sceneNode.Transform().Orientation(rotation);
59 | break;
60 |
61 | case TRANSFORMATION_TRS:
62 | sceneNode.Transform().Scale({ node.scale.x, node.scale.y, node.scale.z });
63 | sceneNode.Transform().Orientation({ node.rotation.x, node.rotation.y, node.rotation.z, node.rotation.w });
64 | sceneNode.Transform().Translation({ node.translation.x, node.translation.y, node.translation.z });
65 | break;
66 |
67 | case TRANSFORMATION_IDENTITY:
68 | default:
69 | // Move along. Nothing to see here.
70 | break;
71 | }
72 | }
73 | } // SceneLoader
74 |
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Sampler.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | using namespace winrt;
12 |
13 | namespace SceneLoader
14 | {
15 | void GLTFVisitor::operator()(const Sampler& sampler, VisitState state, const VisitDefaultAction&)
16 | {
17 | if (state == VisitState::New)
18 | {
19 | if (!m_resourceSet->GetGLTFSamplerById(sampler.id, nullptr))
20 | {
21 | m_resourceSet->StoreGLTFSamplerById(sampler.id, sampler);
22 | }
23 | else
24 | {
25 | Microsoft::glTF::Sampler storedSampler;
26 |
27 | m_resourceSet->GetGLTFSamplerById(sampler.id, &storedSampler);
28 |
29 | assert(storedSampler == sampler);
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Skin.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | using namespace winrt;
12 |
13 | namespace SceneLoader
14 | {
15 | // Skin
16 | void GLTFVisitor::operator()(const Skin& /*skin*/, VisitState /*alreadyVisited*/, const VisitDefaultAction&)
17 | {
18 | }
19 |
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/SceneLoader/GLTFVisitor_Texture.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "GLTFVisitor.h"
8 |
9 | using namespace Microsoft::glTF;
10 |
11 | using namespace winrt;
12 |
13 | namespace SceneLoader
14 | {
15 | void GLTFVisitor::operator()(const Texture& texture, TextureType /*textureType*/, VisitState state, const VisitDefaultAction&)
16 | {
17 | if (state == VisitState::New)
18 | {
19 | if (!m_resourceSet->GetGLTFTextureById(texture.id, nullptr))
20 | {
21 | m_resourceSet->StoreGLTFTextureById(texture.id, texture);
22 | }
23 | else
24 | {
25 | Microsoft::glTF::Texture storedTexture;
26 |
27 | m_resourceSet->GetGLTFTextureById(texture.id, &storedTexture);
28 |
29 | assert(storedTexture == texture);
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/SceneLoader/NugetPackager/SceneLoaderComponent.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SceneLoaderComponent
5 | $version$
6 | developer
7 | developer
8 | https://github.com/windows-toolkit/SceneLoader
9 | false
10 | Parses a GLTF file and produces a WUC SceneNode.
11 |
12 | Copyright 2019
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/SceneLoader/NugetPackager/SceneLoaderComponent.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/SceneLoader/NugetPackager/SceneLoaderComponent.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | $(MSBuildThisFileDirectory)$(Platform)\SceneLoaderComponent.winmd
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/SceneLoader/SceneLoader.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 | #include "SceneLoader.h"
7 |
8 | #include "UtilForIntermingledNamespaces.h"
9 | #include "Bounds3D.h"
10 | #include "GLTFVisitor.h"
11 |
12 | using namespace std;
13 | using namespace Microsoft::glTF;
14 | using namespace SceneLoader;
15 |
16 | namespace winrt {
17 | using namespace Windows::ApplicationModel::Core;
18 | using namespace Windows::Foundation::Collections;
19 | using namespace Windows::UI::Core;
20 | using namespace Windows::UI::Composition;
21 | using namespace Windows::UI::Composition::Scenes;
22 | using namespace Windows::Storage;
23 | using namespace Windows::Storage::Streams;
24 | using namespace Windows::Storage::Pickers;
25 | using namespace Windows::Foundation::Numerics;
26 | using namespace Windows::Foundation;
27 | }
28 | using namespace winrt;
29 |
30 | namespace winrt::SceneLoaderComponent::implementation
31 | {
32 | struct MemBuf : std::streambuf
33 | {
34 | MemBuf(char* begin, char* end) {
35 | this->setg(begin, begin, end);
36 | }
37 | };
38 |
39 | struct StreamReader : public IStreamReader
40 | {
41 | MemBuf m_membuf;
42 |
43 | StreamReader(BYTE* data, UINT32 capacity) :
44 | m_membuf((char*)data, (char*)(data + capacity))
45 | {
46 | }
47 |
48 | virtual ~StreamReader()
49 | {
50 |
51 | }
52 |
53 | shared_ptr GetInputStream(const std::string&) const override
54 | {
55 | auto spIfStream = make_shared(const_cast(&m_membuf));
56 |
57 | if (spIfStream->fail())
58 | {
59 | throw exception("failed to open file");
60 | }
61 | return spIfStream;
62 | }
63 | };
64 |
65 | SceneNode SceneLoader::Load(IBuffer buffer, Compositor compositor)
66 | {
67 | auto memoryBuffer = winrt::Windows::Storage::Streams::Buffer::CreateMemoryBufferOverIBuffer(buffer);
68 | auto memoryBufferReference = memoryBuffer.CreateReference();
69 | auto data = GetDataPointerFromMemoryBuffer(memoryBufferReference);
70 |
71 | SceneNode worldNode = SceneNode::Create(compositor);
72 | SceneNode rootNode = SceneNode::Create(compositor);
73 | worldNode.Children().Append(rootNode);
74 |
75 | //
76 | // Parses the GLTF file and creates the WUC Scenes objects
77 | //
78 | ParseGLTF(data.first, data.second, compositor, rootNode);
79 |
80 | Bounds3D bounds = ComputeTreeBounds(
81 | rootNode,
82 | float4x4::identity());
83 |
84 | float lengthX = bounds.Max().x - bounds.Min().x;
85 | float lengthY = bounds.Max().y - bounds.Min().y;
86 | float lengthZ = bounds.Max().z - bounds.Min().z;
87 |
88 | float maxDimension = max(lengthX, max(lengthY, lengthZ));
89 |
90 | if (maxDimension > 0.0f)
91 | {
92 | float scaleFactor = 300.0f / maxDimension;
93 |
94 | worldNode.Transform().Scale({ scaleFactor, scaleFactor, scaleFactor });
95 | worldNode.Transform().Translation({ 0.0f, -(bounds.Min().y + bounds.Max().y) * scaleFactor / 2, 0.0f });
96 |
97 | }
98 |
99 | return worldNode;
100 | }
101 |
102 | void SceneLoader::ParseGLTF(BYTE* data, UINT32 capacity, Compositor& compositor, SceneNode& rootNode)
103 | {
104 | auto streamReader = make_shared(data, capacity);
105 | auto spifstream = streamReader->GetInputStream("");
106 | auto resourceReader = make_shared(streamReader);
107 |
108 | //////////////////////////////////////////////////////////////////////////////
109 | //
110 | // Document
111 | //
112 | //////////////////////////////////////////////////////////////////////////////
113 | Document gltfDoc = Deserialize(*spifstream);
114 | Validation::Validate(gltfDoc);
115 |
116 | DoIt(gltfDoc, resourceReader, compositor, rootNode);
117 | }
118 |
119 | void SceneLoader::DoIt(Document& gltfDoc, shared_ptr resourceReader, Compositor& compositor, SceneNode& rootNode)
120 | {
121 | //////////////////////////////////////////////////////////////////////////////
122 | //
123 | // Scene
124 | //
125 | //////////////////////////////////////////////////////////////////////////////
126 | auto scene = gltfDoc.GetDefaultScene();
127 |
128 | shared_ptr resourceSet = make_shared(compositor);
129 |
130 | Visit(gltfDoc, DefaultSceneIndex, GLTFVisitor(
131 | compositor,
132 | rootNode,
133 | resourceSet,
134 | resourceReader,
135 | gltfDoc,
136 | scene));
137 |
138 | resourceSet->CreateSceneMaterialObjects();
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/SceneLoader/SceneLoader.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 | #include "SceneLoader.g.h"
8 |
9 | namespace winrt::SceneLoaderComponent::implementation
10 | {
11 | struct SceneLoader : SceneLoaderT
12 | {
13 | SceneLoader() = default;
14 |
15 | winrt::Windows::UI::Composition::Scenes::SceneNode Load(winrt::Windows::Storage::Streams::IBuffer buffer, winrt::Windows::UI::Composition::Compositor compositor);
16 |
17 | private:
18 | void ParseGLTF(
19 | BYTE * data,
20 | UINT32 capacity,
21 | winrt::Windows::UI::Composition::Compositor& compositor,
22 | winrt::Windows::UI::Composition::Scenes::SceneNode& rootNode);
23 | void DoIt(
24 | Microsoft::glTF::Document & gltfDoc,
25 | std::shared_ptr resourceReader,
26 | winrt::Windows::UI::Composition::Compositor& compositor,
27 | winrt::Windows::UI::Composition::Scenes::SceneNode& rootNode);
28 | };
29 | }
30 |
31 | namespace winrt::SceneLoaderComponent::factory_implementation
32 | {
33 | struct SceneLoader : SceneLoaderT
34 | {
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/SceneLoader/SceneLoader.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 670a1d9e-70b7-4796-adc5-1817c10d6040
6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/SceneLoader/SceneLoaderComponent.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
4 |
--------------------------------------------------------------------------------
/SceneLoader/SceneLoaderComponent.idl:
--------------------------------------------------------------------------------
1 | namespace SceneLoaderComponent
2 | {
3 | [default_interface]
4 | runtimeclass SceneLoader
5 | {
6 | SceneLoader();
7 | Windows.UI.Composition.Scenes.SceneNode Load(Windows.Storage.Streams.IBuffer buffer, Windows.UI.Composition.Compositor compositor);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/SceneLoader/SceneResourceSet.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "UtilForIntermingledNamespaces.h"
8 | #include "SceneResourceSet.h"
9 |
10 | using namespace std;
11 | using namespace Microsoft::glTF;
12 |
13 | namespace winrt {
14 | using namespace Windows::UI::Composition;
15 | using namespace Windows::UI::Composition::Scenes;
16 | }
17 | using namespace winrt;
18 |
19 | namespace SceneLoader
20 | {
21 | // If you want to assert when we hit a feature we don't support yet, change this to true.
22 | bool SceneResourceSet::s_assertOnUnimplementedFeature = false;
23 |
24 | SceneWrappingMode
25 | GLTFWrapModeToSceneWrapMode(Microsoft::glTF::WrapMode gltfWrapMode)
26 | {
27 | switch (gltfWrapMode)
28 | {
29 | case Microsoft::glTF::WrapMode::Wrap_CLAMP_TO_EDGE:
30 | return SceneWrappingMode::ClampToEdge;
31 |
32 | case Microsoft::glTF::WrapMode::Wrap_MIRRORED_REPEAT:
33 | return SceneWrappingMode::MirroredRepeat;
34 |
35 | case Microsoft::glTF::WrapMode::Wrap_REPEAT:
36 | default:
37 | return SceneWrappingMode::Repeat;
38 | }
39 | }
40 |
41 |
42 | SceneResourceSet::SceneResourceSet(winrt::Windows::UI::Composition::Compositor compositor) :
43 | m_compositor(compositor),
44 | m_sceneMaterialMap(single_threaded_map()),
45 | m_sceneSurfaceMaterialInputMap(single_threaded_map()),
46 | m_sceneMipMapSurfaceMap(single_threaded_map())
47 | {
48 |
49 | }
50 |
51 |
52 | SceneMetallicRoughnessMaterial
53 | SceneResourceSet::EnsureMaterialById(const std::string id)
54 | {
55 | // Should we trust that the GLTF SDK is traversing correctly the DOM?
56 | if (!m_sceneMaterialMap.HasKey(GetHSTRINGFromStdString(id)))
57 | {
58 | auto sceneMaterial = SceneMetallicRoughnessMaterial::Create(m_compositor);
59 | sceneMaterial.Comment(wstring(id.begin(), id.end()));
60 |
61 | m_sceneMaterialMap.Insert(GetHSTRINGFromStdString(id), sceneMaterial);
62 | }
63 |
64 | return m_sceneMaterialMap.Lookup(GetHSTRINGFromStdString(id));
65 | }
66 |
67 |
68 | CompositionMipmapSurface
69 | SceneResourceSet::EnsureMipMapSurfaceId(
70 | const std::string id,
71 | winrt::Windows::Graphics::SizeInt32 sizePixels,
72 | winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
73 | winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode,
74 | winrt::Windows::UI::Composition::ICompositionGraphicsDevice3 graphicsDevice)
75 | {
76 | // Should we trust that the GLTF SDK is traversing correctly the DOM?
77 | if (!m_sceneMipMapSurfaceMap.HasKey(GetHSTRINGFromStdString(id)))
78 | {
79 | auto mipmapSurface = graphicsDevice.CreateMipmapSurface(
80 | sizePixels,
81 | pixelFormat,
82 | alphaMode);
83 | wstring mipmapId{ id.begin(), id.end() };
84 | mipmapSurface.Comment(mipmapId);
85 |
86 | m_sceneMipMapSurfaceMap.Insert(GetHSTRINGFromStdString(id), mipmapSurface);
87 | }
88 |
89 | return m_sceneMipMapSurfaceMap.Lookup(GetHSTRINGFromStdString(id));
90 | }
91 |
92 |
93 | CompositionMipmapSurface
94 | SceneResourceSet::LookupMipMapSurfaceId(const std::string id)
95 | {
96 | return m_sceneMipMapSurfaceMap.Lookup(GetHSTRINGFromStdString(id));
97 | }
98 |
99 | void
100 | SceneResourceSet::StoreGLTFSamplerById(const std::string id, Microsoft::glTF::Sampler sampler)
101 | {
102 | // Make sure we haven't stored this before
103 | assert(m_gltfSamplerMap.find(GetHSTRINGFromStdString(id)) == m_gltfSamplerMap.end());
104 |
105 | m_gltfSamplerMap.insert(std::map::value_type(GetHSTRINGFromStdString(id), sampler));
106 | }
107 |
108 | bool
109 | SceneResourceSet::GetGLTFSamplerById(const std::string id, Microsoft::glTF::Sampler* pSampler)
110 | {
111 | if (m_gltfSamplerMap.find(GetHSTRINGFromStdString(id)) == m_gltfSamplerMap.end())
112 | {
113 | return false;
114 | }
115 |
116 | if (pSampler)
117 | {
118 | *pSampler = m_gltfSamplerMap.at(GetHSTRINGFromStdString(id));
119 | }
120 |
121 | return true;
122 | }
123 |
124 |
125 | void
126 | SceneResourceSet::StoreGLTFMaterialById(const std::string id, Microsoft::glTF::Material material)
127 | {
128 | // Make sure we haven't stored this before
129 | assert(m_gltfMaterialMap.find(GetHSTRINGFromStdString(id)) == m_gltfMaterialMap.end());
130 |
131 | m_gltfMaterialMap.insert(std::map::value_type(GetHSTRINGFromStdString(id), material));
132 | }
133 |
134 |
135 | bool
136 | SceneResourceSet::GetGLTFMaterialById(const std::string id, Microsoft::glTF::Material* pMaterial)
137 | {
138 | if (m_gltfMaterialMap.find(GetHSTRINGFromStdString(id)) == m_gltfMaterialMap.end())
139 | {
140 | return false;
141 | }
142 |
143 | if (pMaterial)
144 | {
145 | *pMaterial = m_gltfMaterialMap.at(GetHSTRINGFromStdString(id));
146 | }
147 |
148 | return true;
149 | }
150 |
151 |
152 | void
153 | SceneResourceSet::StoreGLTFTextureById(const std::string id, Microsoft::glTF::Texture texture)
154 | {
155 | // Make sure we haven't stored this before
156 | assert(m_gltfTextureMap.find(GetHSTRINGFromStdString(id)) == m_gltfTextureMap.end());
157 |
158 | m_gltfTextureMap.insert(std::map::value_type(GetHSTRINGFromStdString(id), texture));
159 | }
160 |
161 |
162 | bool
163 | SceneResourceSet::GetGLTFTextureById(const std::string id, Microsoft::glTF::Texture* pTexture)
164 | {
165 | if (m_gltfTextureMap.find(GetHSTRINGFromStdString(id)) == m_gltfTextureMap.end())
166 | {
167 | return false;
168 | }
169 |
170 | if (pTexture)
171 | {
172 | *pTexture = m_gltfTextureMap.at(GetHSTRINGFromStdString(id));
173 | }
174 |
175 | return true;
176 | }
177 |
178 |
179 | void
180 | SceneResourceSet::CreateSceneMaterialObjects()
181 | {
182 | for (std::map::iterator materialIterator = m_gltfMaterialMap.begin(); materialIterator != m_gltfMaterialMap.end(); materialIterator++)
183 | {
184 | SceneMetallicRoughnessMaterial sceneMaterial = EnsureMaterialById(materialIterator->second.id);
185 | Microsoft::glTF::Material material = materialIterator->second;
186 |
187 |
188 | // BaseColor
189 | if (material.metallicRoughness.baseColorTexture.textureId != "")
190 | {
191 | auto materialInput = GetMaterialInputFromTextureId(material.metallicRoughness.baseColorTexture.textureId);
192 | sceneMaterial.BaseColorInput(materialInput);
193 |
194 | if (m_latestMeshRendererComponent)
195 | {
196 | m_latestMeshRendererComponent.UVMappings().Insert(L"BaseColorInput",
197 | material.metallicRoughness.baseColorTexture.texCoord == 0 ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1);
198 | }
199 | }
200 |
201 | sceneMaterial.BaseColorFactor({ material.metallicRoughness.baseColorFactor.r, material.metallicRoughness.baseColorFactor.g, material.metallicRoughness.baseColorFactor.b, material.metallicRoughness.baseColorFactor.a });
202 |
203 | // MetallicRoughness
204 | if (material.metallicRoughness.metallicRoughnessTexture.textureId != "")
205 | {
206 | auto materialInput = GetMaterialInputFromTextureId(material.metallicRoughness.metallicRoughnessTexture.textureId);
207 | sceneMaterial.MetallicRoughnessInput(materialInput);
208 |
209 | if (m_latestMeshRendererComponent)
210 | {
211 | m_latestMeshRendererComponent.UVMappings().Insert(L"MetallicRoughnessInput",
212 | material.metallicRoughness.metallicRoughnessTexture.texCoord == 0 ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1);
213 | }
214 | }
215 |
216 | sceneMaterial.RoughnessFactor(material.metallicRoughness.roughnessFactor);
217 |
218 | sceneMaterial.MetallicFactor(material.metallicRoughness.metallicFactor);
219 |
220 | // Normal
221 | if (material.normalTexture.textureId != "")
222 | {
223 | auto materialInput = GetMaterialInputFromTextureId(material.normalTexture.textureId);
224 | sceneMaterial.NormalInput(materialInput);
225 |
226 | if (m_latestMeshRendererComponent)
227 | {
228 | m_latestMeshRendererComponent.UVMappings().Insert(L"NormalInput",
229 | material.normalTexture.texCoord == 0 ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1);
230 | }
231 | }
232 |
233 | sceneMaterial.NormalScale(material.normalTexture.scale);
234 |
235 | // Occlusion
236 | if (material.occlusionTexture.textureId != "")
237 | {
238 | auto materialInput = GetMaterialInputFromTextureId(material.occlusionTexture.textureId);
239 | sceneMaterial.OcclusionInput(materialInput);
240 |
241 | if (m_latestMeshRendererComponent)
242 | {
243 | m_latestMeshRendererComponent.UVMappings().Insert(L"OcclusionInput",
244 | material.occlusionTexture.texCoord == 0 ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1);
245 | }
246 | }
247 |
248 | sceneMaterial.OcclusionStrength(material.occlusionTexture.strength);
249 |
250 | // Emissive
251 | if (material.emissiveTexture.textureId != "")
252 | {
253 | auto materialInput = GetMaterialInputFromTextureId(material.emissiveTexture.textureId);
254 | sceneMaterial.EmissiveInput(materialInput);
255 |
256 | if (m_latestMeshRendererComponent)
257 | {
258 | m_latestMeshRendererComponent.UVMappings().Insert(L"EmissiveInput",
259 | material.emissiveTexture.texCoord == 0 ? SceneAttributeSemantic::TexCoord0 : SceneAttributeSemantic::TexCoord1);
260 | }
261 | }
262 |
263 | sceneMaterial.EmissiveFactor({ material.emissiveFactor.r, material.emissiveFactor.g, material.emissiveFactor.b });
264 |
265 | switch (material.alphaMode) {
266 | case AlphaMode::ALPHA_OPAQUE:
267 | {
268 | sceneMaterial.AlphaMode(SceneAlphaMode::Opaque);
269 | break;
270 | }
271 | case AlphaMode::ALPHA_BLEND:
272 | {
273 | sceneMaterial.AlphaMode(SceneAlphaMode::Blend);
274 | break;
275 | }
276 | case AlphaMode::ALPHA_MASK:
277 | {
278 | sceneMaterial.AlphaMode(SceneAlphaMode::AlphaTest);
279 | break;
280 | }
281 | case AlphaMode::ALPHA_UNKNOWN:
282 | default:
283 | {
284 | UnimplementedFeatureFound();
285 | }
286 | }
287 |
288 | sceneMaterial.AlphaCutoff(material.alphaCutoff);
289 | sceneMaterial.IsDoubleSided(material.doubleSided);
290 | }
291 | }
292 |
293 |
294 | SceneSurfaceMaterialInput
295 | SceneResourceSet::GetMaterialInputFromTextureId(const std::string textureId)
296 | {
297 | static uint16_t sCount = 0;
298 | Microsoft::glTF::Sampler sampler;
299 | Microsoft::glTF::Texture texture;
300 |
301 | bool resultFound;
302 |
303 | resultFound = GetGLTFTextureById(textureId, &texture);
304 | assert(resultFound);
305 |
306 | resultFound = GetGLTFSamplerById(texture.samplerId, &sampler);
307 | assert(resultFound);
308 |
309 | CompositionMipmapSurface mipMapSurface = LookupMipMapSurfaceId(texture.imageId);
310 |
311 | SceneSurfaceMaterialInput sceneSurfaceMaterialInput = SceneSurfaceMaterialInput::Create(m_compositor);
312 | wstringstream ssitoa; ssitoa << sCount;
313 | sceneSurfaceMaterialInput.Comment(ssitoa.str());
314 |
315 | SetSceneSampler(sceneSurfaceMaterialInput, sampler);
316 |
317 | sceneSurfaceMaterialInput.Surface(mipMapSurface);
318 |
319 | ++sCount;
320 |
321 | return sceneSurfaceMaterialInput;
322 | }
323 |
324 |
325 | void
326 | SceneResourceSet::SetSceneSampler(winrt::Windows::UI::Composition::Scenes::SceneSurfaceMaterialInput sceneSurfaceMaterialInput, Microsoft::glTF::Sampler sampler)
327 | {
328 | sceneSurfaceMaterialInput.BitmapInterpolationMode(CompositionBitmapInterpolationMode::MagLinearMinLinearMipLinear);
329 |
330 | sceneSurfaceMaterialInput.WrappingUMode(GLTFWrapModeToSceneWrapMode(sampler.wrapS));
331 |
332 | sceneSurfaceMaterialInput.WrappingVMode(GLTFWrapModeToSceneWrapMode(sampler.wrapT));
333 | }
334 |
335 | void
336 | SceneResourceSet::SetLatestMeshRendererComponent(SceneMeshRendererComponent& meshRendererComponent)
337 | {
338 | m_latestMeshRendererComponent = meshRendererComponent;
339 | }
340 |
341 | void
342 | SceneResourceSet::UnimplementedFeatureFound()
343 | {
344 | if (s_assertOnUnimplementedFeature)
345 | {
346 | assert(false);
347 | }
348 | }
349 |
350 | } // namespace SceneLoader
--------------------------------------------------------------------------------
/SceneLoader/SceneResourceSet.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 | namespace SceneLoader
8 | {
9 | class SceneResourceSet
10 | {
11 | public:
12 | SceneResourceSet(winrt::Windows::UI::Composition::Compositor compositor);
13 |
14 | winrt::Windows::UI::Composition::Scenes::SceneMetallicRoughnessMaterial EnsureMaterialById(const std::string id);
15 |
16 | void StoreGLTFSamplerById(const std::string id, Microsoft::glTF::Sampler sampler);
17 | bool GetGLTFSamplerById(const std::string id, Microsoft::glTF::Sampler* pSampler);
18 |
19 | void StoreGLTFMaterialById(const std::string id, Microsoft::glTF::Material material);
20 | bool GetGLTFMaterialById(const std::string id, Microsoft::glTF::Material* pMaterial);
21 |
22 | void StoreGLTFTextureById(const std::string id, Microsoft::glTF::Texture texture);
23 | bool GetGLTFTextureById(const std::string id, Microsoft::glTF::Texture* pTexture);
24 |
25 | void CreateSceneMaterialObjects();
26 |
27 | void SetSceneSampler(winrt::Windows::UI::Composition::Scenes::SceneSurfaceMaterialInput materialInput, Microsoft::glTF::Sampler sampler);
28 |
29 | winrt::Windows::UI::Composition::Scenes::SceneSurfaceMaterialInput GetMaterialInputFromTextureId(const std::string textureId);
30 |
31 | winrt::Windows::UI::Composition::CompositionMipmapSurface EnsureMipMapSurfaceId(
32 | const std::string id,
33 | winrt::Windows::Graphics::SizeInt32 size,
34 | winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
35 | winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode,
36 | winrt::Windows::UI::Composition::ICompositionGraphicsDevice3 graphicsDevice);
37 |
38 | winrt::Windows::UI::Composition::CompositionMipmapSurface LookupMipMapSurfaceId(const std::string id);
39 |
40 | void SetLatestMeshRendererComponent(winrt::Windows::UI::Composition::Scenes::SceneMeshRendererComponent& meshRendererComponent);
41 |
42 | static void UnimplementedFeatureFound();
43 |
44 | private:
45 | winrt::Windows::UI::Composition::Compositor m_compositor;
46 |
47 | // Only keeps track of the equivalent Mipmap from the DOM into the Scenes API.
48 | winrt::Windows::Foundation::Collections::IMap m_sceneSurfaceMaterialInputMap{ nullptr };
49 |
50 | // Only keeps track of the equivalent Mipmap from the DOM into the Scenes API.
51 | winrt::Windows::Foundation::Collections::IMap m_sceneMipMapSurfaceMap{ nullptr };
52 |
53 | // Only keeps track of the equivalent Materials from the DOM into the Scenes API.
54 | winrt::Windows::Foundation::Collections::IMap m_sceneMaterialMap{ nullptr };
55 |
56 | // Only keeps track of the equivalent Materials from the DOM into the Scenes API.
57 | std::map m_gltfSamplerMap;
58 | std::map m_gltfMaterialMap;
59 | std::map m_gltfTextureMap;
60 |
61 | winrt::Windows::UI::Composition::Scenes::SceneMeshRendererComponent m_latestMeshRendererComponent{ nullptr };
62 |
63 | static bool s_assertOnUnimplementedFeature;
64 | };
65 | } // SceneLoader
--------------------------------------------------------------------------------
/SceneLoader/UtilForIntermingledNamespaces.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
7 | #include "UtilForIntermingledNamespaces.h"
8 |
9 | // WinRT
10 | #include
11 |
12 | // This class doesn't use any "using namespace XXX" because it mixes C++/WinRT
13 | // objects with WinRT ABI Objects (::Windows::Foundation::IMemoryBufferByteAccess).
14 | // The reason for that is that C++/WinRT doesn't expose ::Windows::Foundation::IMemoryBufferByteAccess
15 | // that is being declared into MemoryBuffer.h.
16 | // https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-abi
17 |
18 | namespace SceneLoader
19 | {
20 | winrt::Windows::Foundation::MemoryBuffer
21 | CopyArrayOfBytesToMemoryBuffer(BYTE* data, size_t byteLength)
22 | {
23 | winrt::Windows::Foundation::MemoryBuffer mb{ winrt::Windows::Foundation::MemoryBuffer(static_cast(byteLength)) }; // FIXME: Check bounds sizeof(size_t) > sizeof(UINT32) on x64
24 | winrt::Windows::Foundation::IMemoryBufferReference mbr = mb.CreateReference();
25 | winrt::com_ptr const mba{ mbr.as() };
26 |
27 | {
28 | BYTE* bytes = nullptr;
29 | UINT32 capacity;
30 | mba->GetBuffer(&bytes, &capacity);
31 | for (UINT32 i = 0; i < capacity; ++i)
32 | {
33 | bytes[i] = data[i];
34 | }
35 | }
36 |
37 | return mb;
38 | }
39 |
40 | // std::span is only available in C++20 :(
41 | std::pair
42 | GetDataPointerFromMemoryBuffer(winrt::Windows::Foundation::IMemoryBufferReference memoryBufferReference)
43 | {
44 | auto memoryBufferByteAccess = memoryBufferReference.as();
45 |
46 | BYTE* data;
47 | UINT32 capacity;
48 |
49 | memoryBufferByteAccess->GetBuffer(&data, &capacity);
50 |
51 | return std::make_pair(data, capacity);
52 | }
53 |
54 | winrt::hstring
55 | GetHSTRINGFromStdString(const std::string& s)
56 | {
57 | size_t keyLenght = s.length() + 1;
58 | auto wcstring = std::make_unique(keyLenght);
59 | size_t convertedChars = 0;
60 | mbstowcs_s(&convertedChars, wcstring.get(), keyLenght, s.c_str(), _TRUNCATE);
61 |
62 | return wcstring.get();
63 | }
64 |
65 | } // namespace SceneLoader
66 |
--------------------------------------------------------------------------------
/SceneLoader/UtilForIntermingledNamespaces.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 | namespace SceneLoader {
8 | winrt::Windows::Foundation::MemoryBuffer CopyArrayOfBytesToMemoryBuffer(BYTE* data, size_t byteLength);
9 |
10 | std::pair GetDataPointerFromMemoryBuffer(winrt::Windows::Foundation::IMemoryBufferReference);
11 |
12 | winrt::hstring GetHSTRINGFromStdString(const std::string& s);
13 | }
--------------------------------------------------------------------------------
/SceneLoader/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/SceneLoader/pch.cpp:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #include "pch.h"
6 |
--------------------------------------------------------------------------------
/SceneLoader/pch.h:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | #pragma once
6 |
7 |
8 | // rapidjson (a dependency of GLTF SDK) uses iterators in a way
9 | // that is deprecated on C++17. We can't got back to C++14 because
10 | // C++/WinRT requires C++17. The following line shuts off
11 | // the C++17 warning about the deprecated way of using iterators.
12 | #define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
13 |
14 | // std
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include