├── Assets
├── Floor.png
├── Wall.png
├── Ceiling.png
├── Lampshade.glb
├── TileCorner.bin
├── TileCorner.glb
├── TileEdge.bin
├── TileEdge.glb
├── TileEmpty.bin
├── TileEmpty.glb
├── TileFull.glb
├── TileKitty.bin
├── TileKitty.glb
├── BasicTiles.blend
├── BasicTiles.blend1
├── TileInvCorner.bin
├── TileInvCorner.glb
├── BasicTilesTextured.blend
├── BasicTilesTextured.blend1
├── floor.hlsl
├── TileEmpty.gltf
├── TileInvCorner.gltf
├── TileEdge.gltf
├── TileCorner.gltf
└── TileKitty.gltf
├── Platforms
├── Net
│ └── App.ico
└── Android
│ ├── Resources
│ ├── values
│ │ ├── strings.xml
│ │ └── ic_launcher_background.xml
│ ├── mipmap-hdpi
│ │ ├── appicon_background.png
│ │ └── appicon_foreground.png
│ ├── mipmap-mdpi
│ │ ├── appicon_background.png
│ │ └── appicon_foreground.png
│ ├── mipmap-xhdpi
│ │ ├── appicon_background.png
│ │ └── appicon_foreground.png
│ ├── mipmap-xxhdpi
│ │ ├── appicon_background.png
│ │ └── appicon_foreground.png
│ ├── mipmap-xxxhdpi
│ │ ├── appicon_background.png
│ │ └── appicon_foreground.png
│ ├── mipmap-anydpi-v26
│ │ ├── appicon.xml
│ │ └── appicon_round.xml
│ ├── layout
│ │ └── activity_main.xml
│ └── AboutResources.txt
│ ├── MainActivity.cs
│ └── AndroidManifest.xml
├── MazeShooter.csproj
├── LICENSE
├── Noise.cs
├── MazeShooter.sln
├── Projects
└── Android
│ └── MazeShooter.Android.csproj
├── StaticScene.cs
├── GridBuilder.cs
├── Program.cs
├── .gitignore
└── BakedScene.cs
/Assets/Floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/Floor.png
--------------------------------------------------------------------------------
/Assets/Wall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/Wall.png
--------------------------------------------------------------------------------
/Assets/Ceiling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/Ceiling.png
--------------------------------------------------------------------------------
/Assets/Lampshade.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/Lampshade.glb
--------------------------------------------------------------------------------
/Assets/TileCorner.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileCorner.bin
--------------------------------------------------------------------------------
/Assets/TileCorner.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileCorner.glb
--------------------------------------------------------------------------------
/Assets/TileEdge.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileEdge.bin
--------------------------------------------------------------------------------
/Assets/TileEdge.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileEdge.glb
--------------------------------------------------------------------------------
/Assets/TileEmpty.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileEmpty.bin
--------------------------------------------------------------------------------
/Assets/TileEmpty.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileEmpty.glb
--------------------------------------------------------------------------------
/Assets/TileFull.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileFull.glb
--------------------------------------------------------------------------------
/Assets/TileKitty.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileKitty.bin
--------------------------------------------------------------------------------
/Assets/TileKitty.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileKitty.glb
--------------------------------------------------------------------------------
/Platforms/Net/App.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Net/App.ico
--------------------------------------------------------------------------------
/Assets/BasicTiles.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/BasicTiles.blend
--------------------------------------------------------------------------------
/Assets/BasicTiles.blend1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/BasicTiles.blend1
--------------------------------------------------------------------------------
/Assets/TileInvCorner.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileInvCorner.bin
--------------------------------------------------------------------------------
/Assets/TileInvCorner.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/TileInvCorner.glb
--------------------------------------------------------------------------------
/Assets/BasicTilesTextured.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/BasicTilesTextured.blend
--------------------------------------------------------------------------------
/Assets/BasicTilesTextured.blend1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Assets/BasicTilesTextured.blend1
--------------------------------------------------------------------------------
/Platforms/Android/Resources/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MazeShooter
3 | MazeShooter
4 |
5 |
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-hdpi/appicon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-hdpi/appicon_background.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-hdpi/appicon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-hdpi/appicon_foreground.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-mdpi/appicon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-mdpi/appicon_background.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-mdpi/appicon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-mdpi/appicon_foreground.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xhdpi/appicon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xhdpi/appicon_background.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xhdpi/appicon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xhdpi/appicon_foreground.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2C3E50
4 |
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xxhdpi/appicon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xxhdpi/appicon_background.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xxhdpi/appicon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xxhdpi/appicon_foreground.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xxxhdpi/appicon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xxxhdpi/appicon_background.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-xxxhdpi/appicon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StereoKit/SKTemplate-Universal/HEAD/Platforms/Android/Resources/mipmap-xxxhdpi/appicon_foreground.png
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-anydpi-v26/appicon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Platforms/Android/Resources/mipmap-anydpi-v26/appicon_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Platforms/Android/Resources/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
--------------------------------------------------------------------------------
/MazeShooter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | Exe
5 |
6 | Platforms\Net\App.ico
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 StereoKit
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Assets/floor.hlsl:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | //--name = app/floor
4 |
5 | //--color:color = 0,0,0,1
6 | float4 color;
7 | //--radius = 5,10,0,0
8 | float4 radius;
9 |
10 | struct vsIn {
11 | float4 pos : SV_POSITION;
12 | };
13 | struct psIn {
14 | float4 pos : SV_POSITION;
15 | float4 world : TEXCOORD0;
16 | uint view_id : SV_RenderTargetArrayIndex;
17 | };
18 |
19 | psIn vs(vsIn input, uint id : SV_InstanceID) {
20 | psIn o;
21 | o.view_id = id % sk_view_count;
22 | id = id / sk_view_count;
23 |
24 | o.world = mul(input.pos, sk_inst[id].world);
25 | o.pos = mul(o.world, sk_viewproj[o.view_id]);
26 |
27 | return o;
28 | }
29 | float4 ps(psIn input) : SV_TARGET{
30 | // This line algorithm is inspired by :
31 | // http://madebyevan.com/shaders/grid/
32 |
33 | // Minor grid lines
34 | float2 step = 1 / fwidth(input.world.xz);
35 | float2 grid = abs(frac(input.world.xz - 0.5) - 0.5) * step; // minor grid lines
36 | float dist = sqrt(dot(input.world.xz, input.world.xz)); // transparency falloff
37 | float size = min(grid.x, grid.y);
38 | float val = 1.0 - min(size, 1.0);
39 | val *= saturate(1 - ((dist - radius.x)/radius.y));
40 |
41 | // Major axis lines
42 | const float extraThickness = 0.5;
43 | float2 axes = (abs(input.world.xz)) * step - extraThickness;
44 | size = min(axes.x, axes.y);
45 | float axisVal = 1.0 - min(size, 1.0);
46 | axisVal *= saturate(1 - ((dist - radius.x*1.5)/(radius.y*1.5)));
47 |
48 | // combine, and drop transparent pixels
49 | val = max(val*0.6, axisVal);
50 | if (val <= 0) discard;
51 |
52 | return float4(color.rgb, val);
53 | }
--------------------------------------------------------------------------------
/Noise.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace StereoKit.Framework
6 | {
7 | static class Noise
8 | {
9 | // Based on Squirrel's talk here:
10 | // https://www.gdcvault.com/play/1024365/Math-for-Game-Programmers-Noise
11 | public static uint Hash(int x, uint seed)
12 | {
13 | const uint BIT_NOISE1 = 0x68E31DA4;
14 | const uint BIT_NOISE2 = 0xB5297A4D;
15 | const uint BIT_NOISE3 = 0x1B56C4E9;
16 |
17 | uint mangled = (uint)x;
18 | mangled *= BIT_NOISE1;
19 | mangled += seed;
20 | mangled ^= (mangled >> 8);
21 | mangled += BIT_NOISE2;
22 | mangled ^= (mangled << 8);
23 | mangled *= BIT_NOISE3;
24 | mangled ^= (mangled >> 8);
25 | return mangled;
26 | }
27 |
28 | public static uint Hash(int x, int y, uint seed) {
29 | const int PRIME_NUMBER = 198491317;
30 | return Hash(x + (y * PRIME_NUMBER), seed);
31 | }
32 |
33 | public static float HashF(int x, uint seed)
34 | => Hash(x, seed) / (float)uint.MaxValue;
35 |
36 | public static float HashF(int x, int y, uint seed)
37 | => Hash(x,y,seed) / (float)uint.MaxValue;
38 |
39 | public struct Seed
40 | {
41 | public uint seed;
42 | public int seed_curr;
43 | public Seed(uint seed) { this.seed = seed; seed_curr = 0; }
44 | }
45 | public static Seed NextSeed;
46 | public static float NextF => Hash(NextSeed.seed_curr++, NextSeed.seed) / (float)uint.MaxValue;
47 | public static uint Next => Hash(NextSeed.seed_curr++, NextSeed.seed);
48 | public static int NextRange (int min, int max) => min+(int)(Hash (NextSeed.seed_curr++, NextSeed.seed)%(max-min));
49 | public static float NextRangeF(float min, float max) => min+ (HashF(NextSeed.seed_curr++, NextSeed.seed)*(max-min));
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/MazeShooter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.13.35806.99 d17.13
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MazeShooter", "MazeShooter.csproj", "{F893B4CE-8D54-F506-6F88-3139563BF7F6}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MazeShooter.Android", "Projects\Android\MazeShooter.Android.csproj", "{D48B345E-B437-B70C-946D-692C6348D09C}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {F893B4CE-8D54-F506-6F88-3139563BF7F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {F893B4CE-8D54-F506-6F88-3139563BF7F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {F893B4CE-8D54-F506-6F88-3139563BF7F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {F893B4CE-8D54-F506-6F88-3139563BF7F6}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {D48B345E-B437-B70C-946D-692C6348D09C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {D48B345E-B437-B70C-946D-692C6348D09C}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {D48B345E-B437-B70C-946D-692C6348D09C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
23 | {D48B345E-B437-B70C-946D-692C6348D09C}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {D48B345E-B437-B70C-946D-692C6348D09C}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {D48B345E-B437-B70C-946D-692C6348D09C}.Release|Any CPU.Deploy.0 = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(ExtensibilityGlobals) = postSolution
31 | SolutionGuid = {FFDDDAA3-C347-4616-9044-7B20A1A2307A}
32 | EndGlobalSection
33 | EndGlobal
34 |
--------------------------------------------------------------------------------
/Platforms/Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.xml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.xml
16 |
17 | values/
18 | strings.xml
19 |
20 | For icons, a tool like https://icon.kitchen can be helpful to accelerate the
21 | process of getting all the correct size variants!
22 |
23 | In order to get the build system to recognize Android resources, set the build action to
24 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
25 | instead operate on resource IDs. When you compile an Android application that uses resources,
26 | the build system will package the resources for distribution and generate a class called "Resource"
27 | (this is an Android convention) that contains the tokens for each one of the resources
28 | included. For example, for the above Resources layout, this is what the Resource class would expose:
29 |
30 | public class Resource {
31 | public class Drawable {
32 | public const int icon = 0x123;
33 | }
34 |
35 | public class Layout {
36 | public const int main = 0x456;
37 | }
38 |
39 | public class Strings {
40 | public const int first_string = 0xabc;
41 | public const int second_string = 0xbcd;
42 | }
43 | }
44 |
45 | You would then use Resource.Drawable.icon to reference the drawable/icon.png file, or
46 | Resource.Layout.main to reference the layout/main.xml file, or Resource.Strings.first_string
47 | to reference the first string in the dictionary file values/strings.xml.
--------------------------------------------------------------------------------
/Projects/Android/MazeShooter.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-android
4 | android-arm64
5 | 29
6 | Exe
7 | com.companyname.mazeshooter
8 | 1
9 | 1.0
10 | MazeShooter
11 | true
12 |
13 | Standard
14 | ..\..\Assets
15 | Assets
16 |
17 |
19 | XA4211;XA1006;XA4301
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 | ..\..\Platforms\Android\AndroidManifest.xml
30 | ..\..\Platforms\Android\Resources
31 | ..\..\Platforms\Android\Assets
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/StaticScene.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace StereoKit.Framework
4 | {
5 | public class StaticScene
6 | {
7 | internal List _items = new List();
8 |
9 | public void AddModel(Model model, Matrix at)
10 | {
11 | if (model == null) return;
12 |
13 | foreach (ModelNode node in model.Nodes)
14 | {
15 | if (node.Mesh == null) continue;
16 |
17 | string name = node.Name;
18 | StaticSceneItem item = new StaticSceneItem();
19 | item.visible = name.Contains("[invisible]" ) == false;
20 | item.solid = name.Contains("[intangible]") == false;
21 | item.material = node.Material;
22 | item.mesh = node.Mesh;
23 | item.transform = node.ModelTransform * at;
24 | item.invTransform = item.transform.Inverse;
25 | _items.Add(item);
26 | }
27 | }
28 |
29 | public bool Raycast(Ray worldRay, out Ray at)
30 | {
31 | float closest = float.MaxValue;
32 | at = default;
33 | for (int i = 0; i < _items.Count; i++)
34 | {
35 | if (_items[i].Raycast(worldRay, out Ray curr))
36 | {
37 | float dist = Vec3.DistanceSq(curr.position, worldRay.position);
38 | if (dist < closest)
39 | {
40 | closest = dist;
41 | at = curr;
42 | }
43 | }
44 | }
45 | return closest != float.MaxValue;
46 | }
47 |
48 | public void Draw()
49 | {
50 | for (int i = 0; i < _items.Count; i++)
51 | _items[i].Draw();
52 | }
53 | }
54 |
55 | struct StaticSceneItem
56 | {
57 | internal Matrix transform;
58 | internal Matrix invTransform;
59 | internal Mesh mesh;
60 | internal Material material;
61 | internal bool solid;
62 | internal bool visible;
63 |
64 | public bool Raycast(Ray worldRay, out Ray intersection)
65 | {
66 | if (solid)
67 | {
68 | bool result = mesh.Intersect(invTransform.Transform(worldRay), out intersection);
69 | if (result) intersection = transform.Transform(intersection);
70 | return result;
71 | }
72 | else
73 | {
74 | intersection = default;
75 | return false;
76 | }
77 | }
78 |
79 | public void Draw() { if (visible) mesh.Draw(material, transform); }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Platforms/Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content;
3 | using Android.Graphics;
4 | using Android.OS;
5 | using Android.Runtime;
6 | using Android.Views;
7 | using StereoKit;
8 | using System;
9 | using System.Reflection;
10 | using System.Threading;
11 |
12 | namespace MazeShooter;
13 |
14 | [Activity(Label = "@string/app_name", MainLauncher = true, Exported = true)]
15 | [IntentFilter(new[]{Intent.ActionMain}, Categories = new[]{"org.khronos.openxr.intent.category.IMMERSIVE_HMD", "com.oculus.intent.category.VR", Intent.CategoryLauncher})]
16 | public class MainActivity : Activity, ISurfaceHolderCallback2
17 | {
18 | View surface;
19 |
20 | protected override void OnCreate(Bundle savedInstanceState)
21 | {
22 | base.OnCreate(savedInstanceState);
23 | Run();
24 | SetContentView(Resource.Layout.activity_main);
25 | }
26 |
27 | protected override void OnDestroy()
28 | {
29 | SK.Quit();
30 | base.OnDestroy();
31 | }
32 |
33 | static bool running = false;
34 | void Run()
35 | {
36 | if (running) return;
37 | running = true;
38 |
39 | // Before anything else, give StereoKit the Activity. This should
40 | // be set before any other SK calls, otherwise native library
41 | // loading may fail.
42 | SK.AndroidActivity = this;
43 |
44 | // Set up a surface for StereoKit to draw on, this is only really
45 | // important for flatscreen experiences.
46 | Window.TakeSurface(this);
47 | Window.SetFormat(Format.Unknown);
48 | surface = new View(this);
49 | SetContentView(surface);
50 | surface.RequestFocus();
51 |
52 | // Task.Run will eat exceptions, but Thread.Start doesn't seem to.
53 | new Thread(InvokeStereoKit).Start();
54 | }
55 |
56 | static void InvokeStereoKit()
57 | {
58 | Type entryClass = typeof(Program);
59 | MethodInfo entryPoint = entryClass?.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
60 |
61 | // There are a number of potential method signatures for Main, so
62 | // we need to check each one, and give it the correct values.
63 | //
64 | // Converting MethodInfo into an Action instead of calling Invoke on
65 | // it allows for exceptions to properly bubble up to the IDE.
66 | ParameterInfo[] entryParams = entryPoint?.GetParameters();
67 | if (entryParams == null || entryParams.Length == 0)
68 | {
69 | Action Program_Main = (Action)Delegate.CreateDelegate(typeof(Action), entryPoint);
70 | Program_Main();
71 | }
72 | else if (entryParams?.Length == 1 && entryParams[0].ParameterType == typeof(string[]))
73 | {
74 | Action Program_Main = (Action)Delegate.CreateDelegate(typeof(Action), entryPoint);
75 | Program_Main(new string[] { });
76 | }
77 | else throw new Exception("Couldn't invoke Program.Main!");
78 |
79 | Process.KillProcess(Process.MyPid());
80 | }
81 |
82 | // Events related to surface state changes
83 | public void SurfaceChanged (ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height) => SK.SetWindow(holder.Surface.Handle);
84 | public void SurfaceCreated (ISurfaceHolder holder) => SK.SetWindow(holder.Surface.Handle);
85 | public void SurfaceDestroyed (ISurfaceHolder holder) => SK.SetWindow(IntPtr.Zero);
86 | public void SurfaceRedrawNeeded(ISurfaceHolder holder) { }
87 | }
--------------------------------------------------------------------------------
/Platforms/Android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
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 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/GridBuilder.cs:
--------------------------------------------------------------------------------
1 | using StereoKit;
2 | using StereoKit.Framework;
3 |
4 | namespace StereoKitApp
5 | {
6 | enum TileType
7 | {
8 | /// Corner tile:
9 | /// 1 0
10 | /// 0 0
11 | ///
12 | Corner,
13 | /// Half edge tile:
14 | /// 1 0
15 | /// 1 0
16 | ///
17 | Edge,
18 | /// Kitty corner tile:
19 | /// 1 0
20 | /// 0 1
21 | ///
22 | Kitty,
23 | /// The inverted corner tile:
24 | /// 1 1
25 | /// 1 0
26 | ///
27 | InvCorner,
28 | /// Completely full tile:
29 | /// 1 1
30 | /// 1 1
31 | ///
32 | Full,
33 | Max,
34 | }
35 |
36 | struct TileDefinition
37 | {
38 | public Model model;
39 | public TileType type;
40 | public int matchTile1;
41 | public int matchTile0;
42 |
43 | public TileDefinition(TileType type, int matchTile1, int matchTile0, Model model) { this.type = type; this.matchTile1 = matchTile1; this.matchTile0 = matchTile0; this.model = model; }
44 | public TileDefinition(TileType type, int matchTile1, Model model) { this.type = type; this.matchTile1 = matchTile1; this.matchTile0 = -1; this.model = model; }
45 | }
46 |
47 | class GridBuilder
48 | {
49 | TileDefinition[] tiles;
50 | float tileSize;
51 |
52 | public GridBuilder(float tileSize, params TileDefinition[] tiles)
53 | {
54 | this.tileSize = tileSize;
55 | this.tiles = tiles;
56 | }
57 |
58 | public StaticScene MakeGrid(string grid)
59 | {
60 | string[] lines = grid.Split('\n');
61 | int w = lines[0].Trim().Length;
62 | int h = lines.Length;
63 | byte[] map = new byte[w * h];
64 | for (int y = 0; y < h; y++)
65 | {
66 | for (int x = 0; x < w; x++)
67 | map[x+y*w] = (byte)(lines[y][x] - '0');
68 | }
69 | return MakeGrid(map, w, h);
70 | }
71 |
72 | public StaticScene MakeGrid(byte[] grid, int w, int h)
73 | {
74 | StaticScene result = new StaticScene();
75 | for (int y = 0; y < h-1; y++)
76 | {
77 | for (int x = 0; x < w-1; x++)
78 | {
79 | int a = grid[ x + y *w];
80 | int b = grid[(x+1)+ y *w];
81 | int c = grid[x +(y+1)*w];
82 | int d = grid[(x+1)+(y+1)*w];
83 |
84 | if (!TileId(a,b,c,d, out Model model, out float rot)) return null;
85 |
86 | result.AddModel(model, Matrix.TR(
87 | TilePos(x, y, w, h),
88 | Quat.FromAngles(0, rot, 0)));
89 | }
90 | }
91 | return result;
92 | }
93 |
94 | public Vec3 TilePos(int x, int y, int width, int height)
95 | => new Vec3(
96 | (x - ((width - 1) / 2.0f)) * tileSize,
97 | 0,
98 | (y - ((height - 1) / 2.0f)) * tileSize);
99 |
100 | bool TileId(int a, int b, int c, int d, out Model model, out float rotationDegrees)
101 | {
102 | model = null;
103 | rotationDegrees = 0;
104 |
105 | // Figure out what the two tile types are
106 | int match1 = a;
107 | int match0 = a;
108 | if (b > match1) match1 = b;
109 | else if (c > match1) match1 = c;
110 | else if (d > match1) match1 = d;
111 | if (b < match0) match0 = b;
112 | else if (c < match0) match0 = c;
113 | else if (d < match0) match0 = d;
114 |
115 | // Find the type and rotation of this tile
116 | TileType type = TileType.Full;
117 | int id =
118 | (a==match1?1:0)<<3 |
119 | (b==match1?1:0)<<2 |
120 | (c==match1?1:0)<<1 |
121 | (d==match1?1:0);
122 | switch (id)
123 | {
124 | case 0b0000: type = TileType.Full; break;
125 | case 0b1111: type = TileType.Full; break;
126 | case 0b1000: type = TileType.Corner; rotationDegrees = 180;break;
127 | case 0b0100: type = TileType.Corner; rotationDegrees = 90; break;
128 | case 0b0001: type = TileType.Corner; rotationDegrees = 0; break;
129 | case 0b0010: type = TileType.Corner; rotationDegrees = 270;break;
130 | case 0b1010: type = TileType.Edge; rotationDegrees = 180;break;
131 | case 0b1100: type = TileType.Edge; rotationDegrees = 90; break;
132 | case 0b0101: type = TileType.Edge; rotationDegrees = 0; break;
133 | case 0b0011: type = TileType.Edge; rotationDegrees = 270;break;
134 | case 0b1001: type = TileType.Kitty; break;
135 | case 0b0110: type = TileType.Kitty; rotationDegrees = 90;break;
136 | case 0b1110: type = TileType.InvCorner; rotationDegrees = 180;break;
137 | case 0b1101: type = TileType.InvCorner; rotationDegrees = 90; break;
138 | case 0b0111: type = TileType.InvCorner; rotationDegrees = 0; break;
139 | case 0b1011: type = TileType.InvCorner; rotationDegrees = 270; break;
140 | default: return false;
141 | }
142 |
143 | // Find a definition that matches the tile type and ids
144 | int gridDef = -1;
145 | for (int i = 0; i < tiles.Length; i++)
146 | {
147 | if (tiles[i].type == type &&
148 | match1 == tiles[i].matchTile1 &&
149 | (match0 == tiles[i].matchTile0 || tiles[i].matchTile0 == -1))
150 | {
151 | gridDef = i;
152 | break;
153 | }
154 | }
155 | if (gridDef < 0) return false;
156 |
157 | model = tiles[gridDef].model;
158 |
159 | return true;
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using StereoKit;
2 | using StereoKit.Framework;
3 | using StereoKitApp;
4 | using System.Threading.Tasks;
5 |
6 | public class Program
7 | {
8 | public SKSettings Settings => new SKSettings {
9 | appName = "Light Baking",
10 | mode = AppMode.XR,
11 | origin = OriginMode.Floor
12 | };
13 |
14 | StaticScene scene;
15 | BakedScene bakedScene;
16 | GridBuilder builder;
17 | bool mapDirty = true;
18 |
19 | const int mapWidth = 10;
20 | const int mapHeight = 10;
21 | byte[] map = new byte[mapWidth*mapHeight] {
22 | 1,1,1,1,1,1,1,1,1,1,
23 | 1,0,0,0,0,0,0,0,0,1,
24 | 1,0,0,0,0,0,0,0,0,1,
25 | 1,0,1,1,0,0,1,1,0,1,
26 | 1,0,1,0,0,0,0,1,0,1,
27 | 1,0,1,0,0,0,0,1,0,1,
28 | 1,0,1,0,0,1,0,1,0,1,
29 | 1,0,1,1,0,1,0,1,0,1,
30 | 1,0,0,1,0,0,0,0,0,1,
31 | 1,1,0,1,1,1,1,1,0,1 };
32 | Color[] mapLights = new Color[mapWidth * mapHeight];
33 |
34 | float samples = 64;
35 |
36 | public static void Main(string[] args)
37 | {
38 | Program app = new Program();
39 | SK.Initialize(app.Settings);
40 | app.Init();
41 | SK.Run(app.Step);
42 | }
43 |
44 | public void Init()
45 | {
46 | builder = new GridBuilder(1,
47 | new TileDefinition(TileType.Full, 0, Model.FromFile("TileEmpty.gltf")),
48 | new TileDefinition(TileType.Full, 1, Model.FromFile("TileFull.glb")),
49 | new TileDefinition(TileType.Corner, 1, 0, Model.FromFile("TileCorner.gltf")),
50 | new TileDefinition(TileType.Edge, 1, 0, Model.FromFile("TileEdge.gltf")),
51 | new TileDefinition(TileType.InvCorner, 1, 0, Model.FromFile("TileInvCorner.gltf")),
52 | new TileDefinition(TileType.Kitty, 1, 0, Model.FromFile("TileKitty.gltf")) );
53 | scene = builder.MakeGrid(map,mapWidth,mapHeight);
54 | scene.AddModel(Model.FromFile("Lampshade.glb"), Matrix.TRS(new Vec3(-0.75f, 1.5f, -3.52f), new Vec3(-45,0,0), 0.5f));
55 |
56 | bakedScene = new BakedScene();
57 | bakedScene.SetSky(Renderer.SkyLight);
58 | mapLights[4 + 2 * mapWidth] = new Color(1, 1, 1);
59 | //bakedScene.AddLight(new Vec3(-0.75f, 1.5f, -3.52f), Color.HSV((float)r.NextDouble(), 0.4f+(float)r.NextDouble() * 0.5f, 1).ToLinear(), 200f);
60 | }
61 |
62 | public void Step()
63 | {
64 | bakedScene.Draw();
65 | bakedScene.DrawDebug();
66 |
67 | WindowMapEditor();
68 |
69 | if (mapDirty && !bakedScene.Baking)
70 | {
71 | mapDirty = false;
72 | RebuildMap(true);
73 | }
74 | }
75 |
76 | Pose mapWindowPose = new Pose(0.2f, 1.5f, -0.5f, Quat.LookDir(0, 0, 1));
77 | int mapEditMode = 0;
78 | float mapColorHue = 0;
79 | void WindowMapEditor()
80 | {
81 | UI.WindowBegin("Map Editor", ref mapWindowPose);
82 |
83 | if (UI.Radio("Map", mapEditMode == 0)) mapEditMode = 0;
84 | UI.SameLine();
85 | if (UI.Radio("Lighting", mapEditMode == 1)) mapEditMode = 1;
86 |
87 | if (mapEditMode == 1)
88 | {
89 | UI.SameLine();
90 | UI.Label("Hue");
91 | UI.SameLine();
92 | UI.PushTint(Color.HSV(mapColorHue, 0.2f, 1));
93 | UI.HSlider("Hue", ref mapColorHue, 0, 1, 0);
94 | UI.PopTint();
95 | }
96 |
97 | if (bakedScene.Baking)
98 | {
99 | UI.Label("Baking...");
100 | UI.SameLine();
101 | UI.ProgressBar(bakedScene.BakingProgress);
102 | } else {
103 | if (UI.Button("Bake"))
104 | RebuildMap(false);
105 | UI.SameLine();
106 | UI.Label("Samples"); UI.SameLine(); UI.HSlider("Samples", ref samples, 0, 512, 1);
107 | }
108 |
109 | UI.HSeparator();
110 |
111 | Vec2 btnSize = V.XY(0.03f, 0.03f);
112 | if (mapEditMode == 0)
113 | {
114 | for (int y = 0; y < mapHeight; y++)
115 | {
116 | for (int x = 0; x < mapWidth; x++)
117 | {
118 | int i = x + y * mapWidth;
119 | UI.PushId(i);
120 | bool solid = map[i] == 1;
121 | if (UI.Toggle(solid ? "X" : " ", ref solid, null, Sprite.ToggleOff, UIBtnLayout.CenterNoText, btnSize))
122 | {
123 | map[i] = solid ? (byte)1 : (byte)0;
124 | mapDirty = true;
125 | }
126 | UI.PopId();
127 | UI.SameLine();
128 | }
129 | UI.NextLine();
130 | }
131 | }
132 | else if (mapEditMode == 1)
133 | {
134 | for (int y = 0; y < mapHeight; y++)
135 | {
136 | for (int x = 0; x < mapWidth; x++)
137 | {
138 | int i = x + y * mapWidth;
139 | UI.PushId(i + 1000);
140 | bool present = mapLights[i].a > 0;
141 | UI.PushTint(present ? mapLights[i] : Color.White);
142 | if (UI.Toggle(present ? "*" : " ", ref present, null, Sprite.RadioOn, UIBtnLayout.CenterNoText, btnSize))
143 | {
144 | mapLights[i] = Color.HSV(mapColorHue, lightSat, lightVal).ToLinear();
145 | mapLights[i].a = present ? 1 : 0;
146 | mapDirty = true;
147 | }
148 | UI.PopTint();
149 | UI.PopId();
150 | UI.SameLine();
151 | }
152 | UI.NextLine();
153 | }
154 | }
155 |
156 | UI.WindowEnd();
157 | }
158 |
159 | const float lightSat = 0.3f;
160 | const float lightVal = 1;
161 | const float lightintensity = 0.9f;
162 | void RebuildMap(bool fast)
163 | {
164 | bakedScene.ClearLights();
165 | for (int y = 0; y < mapHeight; y++)
166 | {
167 | for (int x = 0; x < mapWidth; x++)
168 | {
169 | int i = x + y * mapWidth;
170 | if (mapLights[i].a > 0)
171 | bakedScene.AddPointLight(builder.TilePos(x, y, mapWidth, mapHeight) + new Vec3(-0.5f,1.5f,-0.5f), mapLights[i], lightintensity);
172 | }
173 | }
174 |
175 | bakedScene.AddDirectionalLight(new Vec3(-1, -1.1f, 0.4f), Color.HSV(0.1f, 0.3f, 1.0f).ToLinear(), .5f);
176 | scene = builder.MakeGrid(map, mapWidth, mapHeight);
177 | if (!bakedScene.Baking)
178 | Task.Run(() => bakedScene.Bake(scene, fast?0:(int)samples, !fast));
179 | }
180 | }
--------------------------------------------------------------------------------
/.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 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/Assets/TileEmpty.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "generator" : "Khronos glTF Blender I/O v1.7.33",
4 | "version" : "2.0"
5 | },
6 | "scene" : 0,
7 | "scenes" : [
8 | {
9 | "name" : "Scene",
10 | "nodes" : [
11 | 1
12 | ]
13 | }
14 | ],
15 | "nodes" : [
16 | {
17 | "mesh" : 0,
18 | "name" : "[invisible]EmptyCollider"
19 | },
20 | {
21 | "children" : [
22 | 0
23 | ],
24 | "mesh" : 1,
25 | "name" : "[intangible]Empty"
26 | }
27 | ],
28 | "materials" : [
29 | {
30 | "doubleSided" : true,
31 | "name" : "Wall",
32 | "pbrMetallicRoughness" : {
33 | "baseColorTexture" : {
34 | "index" : 0
35 | },
36 | "metallicFactor" : 0,
37 | "roughnessFactor" : 0.4000000059604645
38 | }
39 | },
40 | {
41 | "doubleSided" : true,
42 | "name" : "Floor",
43 | "pbrMetallicRoughness" : {
44 | "baseColorTexture" : {
45 | "index" : 1
46 | },
47 | "metallicFactor" : 0,
48 | "roughnessFactor" : 0.5
49 | }
50 | },
51 | {
52 | "doubleSided" : true,
53 | "name" : "Ceiling",
54 | "pbrMetallicRoughness" : {
55 | "baseColorTexture" : {
56 | "index" : 2
57 | },
58 | "metallicFactor" : 0,
59 | "roughnessFactor" : 0.5
60 | }
61 | }
62 | ],
63 | "meshes" : [
64 | {
65 | "name" : "Cube.009",
66 | "primitives" : [
67 | {
68 | "attributes" : {
69 | "POSITION" : 0,
70 | "NORMAL" : 1,
71 | "TEXCOORD_0" : 2
72 | },
73 | "indices" : 3,
74 | "material" : 0
75 | }
76 | ]
77 | },
78 | {
79 | "name" : "Cube",
80 | "primitives" : [
81 | {
82 | "attributes" : {
83 | "POSITION" : 4,
84 | "NORMAL" : 5,
85 | "TEXCOORD_0" : 6
86 | },
87 | "indices" : 7,
88 | "material" : 1
89 | },
90 | {
91 | "attributes" : {
92 | "POSITION" : 8,
93 | "NORMAL" : 9,
94 | "TEXCOORD_0" : 10
95 | },
96 | "indices" : 7,
97 | "material" : 2
98 | }
99 | ]
100 | }
101 | ],
102 | "textures" : [
103 | {
104 | "sampler" : 0,
105 | "source" : 0
106 | },
107 | {
108 | "sampler" : 0,
109 | "source" : 1
110 | },
111 | {
112 | "sampler" : 0,
113 | "source" : 2
114 | }
115 | ],
116 | "images" : [
117 | {
118 | "mimeType" : "image/png",
119 | "name" : "Wall",
120 | "uri" : "Wall.png"
121 | },
122 | {
123 | "mimeType" : "image/png",
124 | "name" : "Floor",
125 | "uri" : "Floor.png"
126 | },
127 | {
128 | "mimeType" : "image/png",
129 | "name" : "Ceiling",
130 | "uri" : "Ceiling.png"
131 | }
132 | ],
133 | "accessors" : [
134 | {
135 | "bufferView" : 0,
136 | "componentType" : 5126,
137 | "count" : 8,
138 | "max" : [
139 | 0.5100000500679016,
140 | 2.500000476837158,
141 | 0.5100000500679016
142 | ],
143 | "min" : [
144 | -0.5100000500679016,
145 | 0,
146 | -0.5100000500679016
147 | ],
148 | "type" : "VEC3"
149 | },
150 | {
151 | "bufferView" : 1,
152 | "componentType" : 5126,
153 | "count" : 8,
154 | "type" : "VEC3"
155 | },
156 | {
157 | "bufferView" : 2,
158 | "componentType" : 5126,
159 | "count" : 8,
160 | "type" : "VEC2"
161 | },
162 | {
163 | "bufferView" : 3,
164 | "componentType" : 5123,
165 | "count" : 12,
166 | "type" : "SCALAR"
167 | },
168 | {
169 | "bufferView" : 4,
170 | "componentType" : 5126,
171 | "count" : 25,
172 | "max" : [
173 | 0.5000000596046448,
174 | 0,
175 | 0.5000000596046448
176 | ],
177 | "min" : [
178 | -0.5000000596046448,
179 | 0,
180 | -0.5000000596046448
181 | ],
182 | "type" : "VEC3"
183 | },
184 | {
185 | "bufferView" : 5,
186 | "componentType" : 5126,
187 | "count" : 25,
188 | "type" : "VEC3"
189 | },
190 | {
191 | "bufferView" : 6,
192 | "componentType" : 5126,
193 | "count" : 25,
194 | "type" : "VEC2"
195 | },
196 | {
197 | "bufferView" : 7,
198 | "componentType" : 5123,
199 | "count" : 96,
200 | "type" : "SCALAR"
201 | },
202 | {
203 | "bufferView" : 8,
204 | "componentType" : 5126,
205 | "count" : 25,
206 | "max" : [
207 | 0.5000000596046448,
208 | 2.500000476837158,
209 | 0.5000000596046448
210 | ],
211 | "min" : [
212 | -0.5000000596046448,
213 | 2.5,
214 | -0.5000000596046448
215 | ],
216 | "type" : "VEC3"
217 | },
218 | {
219 | "bufferView" : 9,
220 | "componentType" : 5126,
221 | "count" : 25,
222 | "type" : "VEC3"
223 | },
224 | {
225 | "bufferView" : 10,
226 | "componentType" : 5126,
227 | "count" : 25,
228 | "type" : "VEC2"
229 | }
230 | ],
231 | "bufferViews" : [
232 | {
233 | "buffer" : 0,
234 | "byteLength" : 96,
235 | "byteOffset" : 0
236 | },
237 | {
238 | "buffer" : 0,
239 | "byteLength" : 96,
240 | "byteOffset" : 96
241 | },
242 | {
243 | "buffer" : 0,
244 | "byteLength" : 64,
245 | "byteOffset" : 192
246 | },
247 | {
248 | "buffer" : 0,
249 | "byteLength" : 24,
250 | "byteOffset" : 256
251 | },
252 | {
253 | "buffer" : 0,
254 | "byteLength" : 300,
255 | "byteOffset" : 280
256 | },
257 | {
258 | "buffer" : 0,
259 | "byteLength" : 300,
260 | "byteOffset" : 580
261 | },
262 | {
263 | "buffer" : 0,
264 | "byteLength" : 200,
265 | "byteOffset" : 880
266 | },
267 | {
268 | "buffer" : 0,
269 | "byteLength" : 192,
270 | "byteOffset" : 1080
271 | },
272 | {
273 | "buffer" : 0,
274 | "byteLength" : 300,
275 | "byteOffset" : 1272
276 | },
277 | {
278 | "buffer" : 0,
279 | "byteLength" : 300,
280 | "byteOffset" : 1572
281 | },
282 | {
283 | "buffer" : 0,
284 | "byteLength" : 200,
285 | "byteOffset" : 1872
286 | }
287 | ],
288 | "samplers" : [
289 | {
290 | "magFilter" : 9729,
291 | "minFilter" : 9987
292 | }
293 | ],
294 | "buffers" : [
295 | {
296 | "byteLength" : 2072,
297 | "uri" : "TileEmpty.bin"
298 | }
299 | ]
300 | }
301 |
--------------------------------------------------------------------------------
/Assets/TileInvCorner.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "generator" : "Khronos glTF Blender I/O v1.7.33",
4 | "version" : "2.0"
5 | },
6 | "scene" : 0,
7 | "scenes" : [
8 | {
9 | "name" : "Scene",
10 | "nodes" : [
11 | 1
12 | ]
13 | }
14 | ],
15 | "nodes" : [
16 | {
17 | "mesh" : 0,
18 | "name" : "[invisible]InvCornerCollider"
19 | },
20 | {
21 | "children" : [
22 | 0
23 | ],
24 | "mesh" : 1,
25 | "name" : "[intangible]InvCorner"
26 | }
27 | ],
28 | "materials" : [
29 | {
30 | "doubleSided" : true,
31 | "name" : "Wall",
32 | "pbrMetallicRoughness" : {
33 | "baseColorTexture" : {
34 | "index" : 0
35 | },
36 | "metallicFactor" : 0,
37 | "roughnessFactor" : 0.4000000059604645
38 | }
39 | },
40 | {
41 | "doubleSided" : true,
42 | "name" : "Ceiling",
43 | "pbrMetallicRoughness" : {
44 | "baseColorTexture" : {
45 | "index" : 1
46 | },
47 | "metallicFactor" : 0,
48 | "roughnessFactor" : 0.5
49 | }
50 | },
51 | {
52 | "doubleSided" : true,
53 | "name" : "Floor",
54 | "pbrMetallicRoughness" : {
55 | "baseColorTexture" : {
56 | "index" : 2
57 | },
58 | "metallicFactor" : 0,
59 | "roughnessFactor" : 0.5
60 | }
61 | }
62 | ],
63 | "meshes" : [
64 | {
65 | "name" : "Cube.010",
66 | "primitives" : [
67 | {
68 | "attributes" : {
69 | "POSITION" : 0,
70 | "NORMAL" : 1,
71 | "TEXCOORD_0" : 2
72 | },
73 | "indices" : 3,
74 | "material" : 0
75 | }
76 | ]
77 | },
78 | {
79 | "name" : "Cube.004",
80 | "primitives" : [
81 | {
82 | "attributes" : {
83 | "POSITION" : 4,
84 | "NORMAL" : 5,
85 | "TEXCOORD_0" : 6
86 | },
87 | "indices" : 7,
88 | "material" : 0
89 | },
90 | {
91 | "attributes" : {
92 | "POSITION" : 8,
93 | "NORMAL" : 9,
94 | "TEXCOORD_0" : 10
95 | },
96 | "indices" : 11,
97 | "material" : 1
98 | },
99 | {
100 | "attributes" : {
101 | "POSITION" : 12,
102 | "NORMAL" : 13,
103 | "TEXCOORD_0" : 14
104 | },
105 | "indices" : 15,
106 | "material" : 2
107 | }
108 | ]
109 | }
110 | ],
111 | "textures" : [
112 | {
113 | "sampler" : 0,
114 | "source" : 0
115 | },
116 | {
117 | "sampler" : 0,
118 | "source" : 1
119 | },
120 | {
121 | "sampler" : 0,
122 | "source" : 2
123 | }
124 | ],
125 | "images" : [
126 | {
127 | "mimeType" : "image/png",
128 | "name" : "Wall",
129 | "uri" : "Wall.png"
130 | },
131 | {
132 | "mimeType" : "image/png",
133 | "name" : "Ceiling",
134 | "uri" : "Ceiling.png"
135 | },
136 | {
137 | "mimeType" : "image/png",
138 | "name" : "Floor",
139 | "uri" : "Floor.png"
140 | }
141 | ],
142 | "accessors" : [
143 | {
144 | "bufferView" : 0,
145 | "componentType" : 5126,
146 | "count" : 16,
147 | "max" : [
148 | 0.5100000500679016,
149 | 2.500000238418579,
150 | 0.5100000500679016
151 | ],
152 | "min" : [
153 | 0,
154 | 0,
155 | 0
156 | ],
157 | "type" : "VEC3"
158 | },
159 | {
160 | "bufferView" : 1,
161 | "componentType" : 5126,
162 | "count" : 16,
163 | "type" : "VEC3"
164 | },
165 | {
166 | "bufferView" : 2,
167 | "componentType" : 5126,
168 | "count" : 16,
169 | "type" : "VEC2"
170 | },
171 | {
172 | "bufferView" : 3,
173 | "componentType" : 5123,
174 | "count" : 24,
175 | "type" : "SCALAR"
176 | },
177 | {
178 | "bufferView" : 4,
179 | "componentType" : 5126,
180 | "count" : 45,
181 | "max" : [
182 | 0.5000000596046448,
183 | 2.500000238418579,
184 | 0.5000000596046448
185 | ],
186 | "min" : [
187 | 0,
188 | 0,
189 | 0
190 | ],
191 | "type" : "VEC3"
192 | },
193 | {
194 | "bufferView" : 5,
195 | "componentType" : 5126,
196 | "count" : 45,
197 | "type" : "VEC3"
198 | },
199 | {
200 | "bufferView" : 6,
201 | "componentType" : 5126,
202 | "count" : 45,
203 | "type" : "VEC2"
204 | },
205 | {
206 | "bufferView" : 7,
207 | "componentType" : 5123,
208 | "count" : 192,
209 | "type" : "SCALAR"
210 | },
211 | {
212 | "bufferView" : 8,
213 | "componentType" : 5126,
214 | "count" : 9,
215 | "max" : [
216 | 0.5000000596046448,
217 | 2.500000238418579,
218 | 0.5000000596046448
219 | ],
220 | "min" : [
221 | 0,
222 | 2.500000238418579,
223 | 0
224 | ],
225 | "type" : "VEC3"
226 | },
227 | {
228 | "bufferView" : 9,
229 | "componentType" : 5126,
230 | "count" : 9,
231 | "type" : "VEC3"
232 | },
233 | {
234 | "bufferView" : 10,
235 | "componentType" : 5126,
236 | "count" : 9,
237 | "type" : "VEC2"
238 | },
239 | {
240 | "bufferView" : 11,
241 | "componentType" : 5123,
242 | "count" : 24,
243 | "type" : "SCALAR"
244 | },
245 | {
246 | "bufferView" : 12,
247 | "componentType" : 5126,
248 | "count" : 9,
249 | "max" : [
250 | 0.5000000596046448,
251 | 0,
252 | 0.5000000596046448
253 | ],
254 | "min" : [
255 | 0,
256 | 0,
257 | 0
258 | ],
259 | "type" : "VEC3"
260 | },
261 | {
262 | "bufferView" : 13,
263 | "componentType" : 5126,
264 | "count" : 9,
265 | "type" : "VEC3"
266 | },
267 | {
268 | "bufferView" : 14,
269 | "componentType" : 5126,
270 | "count" : 9,
271 | "type" : "VEC2"
272 | },
273 | {
274 | "bufferView" : 15,
275 | "componentType" : 5123,
276 | "count" : 24,
277 | "type" : "SCALAR"
278 | }
279 | ],
280 | "bufferViews" : [
281 | {
282 | "buffer" : 0,
283 | "byteLength" : 192,
284 | "byteOffset" : 0
285 | },
286 | {
287 | "buffer" : 0,
288 | "byteLength" : 192,
289 | "byteOffset" : 192
290 | },
291 | {
292 | "buffer" : 0,
293 | "byteLength" : 128,
294 | "byteOffset" : 384
295 | },
296 | {
297 | "buffer" : 0,
298 | "byteLength" : 48,
299 | "byteOffset" : 512
300 | },
301 | {
302 | "buffer" : 0,
303 | "byteLength" : 540,
304 | "byteOffset" : 560
305 | },
306 | {
307 | "buffer" : 0,
308 | "byteLength" : 540,
309 | "byteOffset" : 1100
310 | },
311 | {
312 | "buffer" : 0,
313 | "byteLength" : 360,
314 | "byteOffset" : 1640
315 | },
316 | {
317 | "buffer" : 0,
318 | "byteLength" : 384,
319 | "byteOffset" : 2000
320 | },
321 | {
322 | "buffer" : 0,
323 | "byteLength" : 108,
324 | "byteOffset" : 2384
325 | },
326 | {
327 | "buffer" : 0,
328 | "byteLength" : 108,
329 | "byteOffset" : 2492
330 | },
331 | {
332 | "buffer" : 0,
333 | "byteLength" : 72,
334 | "byteOffset" : 2600
335 | },
336 | {
337 | "buffer" : 0,
338 | "byteLength" : 48,
339 | "byteOffset" : 2672
340 | },
341 | {
342 | "buffer" : 0,
343 | "byteLength" : 108,
344 | "byteOffset" : 2720
345 | },
346 | {
347 | "buffer" : 0,
348 | "byteLength" : 108,
349 | "byteOffset" : 2828
350 | },
351 | {
352 | "buffer" : 0,
353 | "byteLength" : 72,
354 | "byteOffset" : 2936
355 | },
356 | {
357 | "buffer" : 0,
358 | "byteLength" : 48,
359 | "byteOffset" : 3008
360 | }
361 | ],
362 | "samplers" : [
363 | {
364 | "magFilter" : 9729,
365 | "minFilter" : 9987
366 | }
367 | ],
368 | "buffers" : [
369 | {
370 | "byteLength" : 3056,
371 | "uri" : "TileInvCorner.bin"
372 | }
373 | ]
374 | }
375 |
--------------------------------------------------------------------------------
/Assets/TileEdge.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "generator" : "Khronos glTF Blender I/O v1.7.33",
4 | "version" : "2.0"
5 | },
6 | "scene" : 0,
7 | "scenes" : [
8 | {
9 | "name" : "Scene",
10 | "nodes" : [
11 | 1
12 | ]
13 | }
14 | ],
15 | "nodes" : [
16 | {
17 | "mesh" : 0,
18 | "name" : "[invisible]EdgeCollider"
19 | },
20 | {
21 | "children" : [
22 | 0
23 | ],
24 | "mesh" : 1,
25 | "name" : "[intangible]Edge"
26 | }
27 | ],
28 | "materials" : [
29 | {
30 | "doubleSided" : true,
31 | "name" : "Wall",
32 | "pbrMetallicRoughness" : {
33 | "baseColorTexture" : {
34 | "index" : 0
35 | },
36 | "metallicFactor" : 0,
37 | "roughnessFactor" : 0.4000000059604645
38 | }
39 | },
40 | {
41 | "doubleSided" : true,
42 | "name" : "Ceiling",
43 | "pbrMetallicRoughness" : {
44 | "baseColorTexture" : {
45 | "index" : 1
46 | },
47 | "metallicFactor" : 0,
48 | "roughnessFactor" : 0.5
49 | }
50 | },
51 | {
52 | "doubleSided" : true,
53 | "name" : "Floor",
54 | "pbrMetallicRoughness" : {
55 | "baseColorTexture" : {
56 | "index" : 2
57 | },
58 | "metallicFactor" : 0,
59 | "roughnessFactor" : 0.5
60 | }
61 | }
62 | ],
63 | "meshes" : [
64 | {
65 | "name" : "Cube.008",
66 | "primitives" : [
67 | {
68 | "attributes" : {
69 | "POSITION" : 0,
70 | "NORMAL" : 1,
71 | "TEXCOORD_0" : 2
72 | },
73 | "indices" : 3,
74 | "material" : 0
75 | }
76 | ]
77 | },
78 | {
79 | "name" : "Cube.006",
80 | "primitives" : [
81 | {
82 | "attributes" : {
83 | "POSITION" : 4,
84 | "NORMAL" : 5,
85 | "TEXCOORD_0" : 6
86 | },
87 | "indices" : 7,
88 | "material" : 0
89 | },
90 | {
91 | "attributes" : {
92 | "POSITION" : 8,
93 | "NORMAL" : 9,
94 | "TEXCOORD_0" : 10
95 | },
96 | "indices" : 11,
97 | "material" : 1
98 | },
99 | {
100 | "attributes" : {
101 | "POSITION" : 12,
102 | "NORMAL" : 13,
103 | "TEXCOORD_0" : 14
104 | },
105 | "indices" : 15,
106 | "material" : 2
107 | }
108 | ]
109 | }
110 | ],
111 | "textures" : [
112 | {
113 | "sampler" : 0,
114 | "source" : 0
115 | },
116 | {
117 | "sampler" : 0,
118 | "source" : 1
119 | },
120 | {
121 | "sampler" : 0,
122 | "source" : 2
123 | }
124 | ],
125 | "images" : [
126 | {
127 | "mimeType" : "image/png",
128 | "name" : "Wall",
129 | "uri" : "Wall.png"
130 | },
131 | {
132 | "mimeType" : "image/png",
133 | "name" : "Ceiling",
134 | "uri" : "Ceiling.png"
135 | },
136 | {
137 | "mimeType" : "image/png",
138 | "name" : "Floor",
139 | "uri" : "Floor.png"
140 | }
141 | ],
142 | "accessors" : [
143 | {
144 | "bufferView" : 0,
145 | "componentType" : 5126,
146 | "count" : 12,
147 | "max" : [
148 | 0.5100000500679016,
149 | 2.500000238418579,
150 | 0.5100000500679016
151 | ],
152 | "min" : [
153 | 0,
154 | 0,
155 | -0.5100000500679016
156 | ],
157 | "type" : "VEC3"
158 | },
159 | {
160 | "bufferView" : 1,
161 | "componentType" : 5126,
162 | "count" : 12,
163 | "type" : "VEC3"
164 | },
165 | {
166 | "bufferView" : 2,
167 | "componentType" : 5126,
168 | "count" : 12,
169 | "type" : "VEC2"
170 | },
171 | {
172 | "bufferView" : 3,
173 | "componentType" : 5123,
174 | "count" : 18,
175 | "type" : "SCALAR"
176 | },
177 | {
178 | "bufferView" : 4,
179 | "componentType" : 5126,
180 | "count" : 45,
181 | "max" : [
182 | 0,
183 | 2.500000238418579,
184 | 0.5000000596046448
185 | ],
186 | "min" : [
187 | 0,
188 | 0,
189 | -0.5000000596046448
190 | ],
191 | "type" : "VEC3"
192 | },
193 | {
194 | "bufferView" : 5,
195 | "componentType" : 5126,
196 | "count" : 45,
197 | "type" : "VEC3"
198 | },
199 | {
200 | "bufferView" : 6,
201 | "componentType" : 5126,
202 | "count" : 45,
203 | "type" : "VEC2"
204 | },
205 | {
206 | "bufferView" : 7,
207 | "componentType" : 5123,
208 | "count" : 192,
209 | "type" : "SCALAR"
210 | },
211 | {
212 | "bufferView" : 8,
213 | "componentType" : 5126,
214 | "count" : 15,
215 | "max" : [
216 | 0.5000000596046448,
217 | 2.500000238418579,
218 | 0.5000000596046448
219 | ],
220 | "min" : [
221 | 0,
222 | 2.500000238418579,
223 | -0.5000000596046448
224 | ],
225 | "type" : "VEC3"
226 | },
227 | {
228 | "bufferView" : 9,
229 | "componentType" : 5126,
230 | "count" : 15,
231 | "type" : "VEC3"
232 | },
233 | {
234 | "bufferView" : 10,
235 | "componentType" : 5126,
236 | "count" : 15,
237 | "type" : "VEC2"
238 | },
239 | {
240 | "bufferView" : 11,
241 | "componentType" : 5123,
242 | "count" : 48,
243 | "type" : "SCALAR"
244 | },
245 | {
246 | "bufferView" : 12,
247 | "componentType" : 5126,
248 | "count" : 15,
249 | "max" : [
250 | 0.5000000596046448,
251 | 0,
252 | 0.5000000596046448
253 | ],
254 | "min" : [
255 | 0,
256 | 0,
257 | -0.5000000596046448
258 | ],
259 | "type" : "VEC3"
260 | },
261 | {
262 | "bufferView" : 13,
263 | "componentType" : 5126,
264 | "count" : 15,
265 | "type" : "VEC3"
266 | },
267 | {
268 | "bufferView" : 14,
269 | "componentType" : 5126,
270 | "count" : 15,
271 | "type" : "VEC2"
272 | },
273 | {
274 | "bufferView" : 15,
275 | "componentType" : 5123,
276 | "count" : 48,
277 | "type" : "SCALAR"
278 | }
279 | ],
280 | "bufferViews" : [
281 | {
282 | "buffer" : 0,
283 | "byteLength" : 144,
284 | "byteOffset" : 0
285 | },
286 | {
287 | "buffer" : 0,
288 | "byteLength" : 144,
289 | "byteOffset" : 144
290 | },
291 | {
292 | "buffer" : 0,
293 | "byteLength" : 96,
294 | "byteOffset" : 288
295 | },
296 | {
297 | "buffer" : 0,
298 | "byteLength" : 36,
299 | "byteOffset" : 384
300 | },
301 | {
302 | "buffer" : 0,
303 | "byteLength" : 540,
304 | "byteOffset" : 420
305 | },
306 | {
307 | "buffer" : 0,
308 | "byteLength" : 540,
309 | "byteOffset" : 960
310 | },
311 | {
312 | "buffer" : 0,
313 | "byteLength" : 360,
314 | "byteOffset" : 1500
315 | },
316 | {
317 | "buffer" : 0,
318 | "byteLength" : 384,
319 | "byteOffset" : 1860
320 | },
321 | {
322 | "buffer" : 0,
323 | "byteLength" : 180,
324 | "byteOffset" : 2244
325 | },
326 | {
327 | "buffer" : 0,
328 | "byteLength" : 180,
329 | "byteOffset" : 2424
330 | },
331 | {
332 | "buffer" : 0,
333 | "byteLength" : 120,
334 | "byteOffset" : 2604
335 | },
336 | {
337 | "buffer" : 0,
338 | "byteLength" : 96,
339 | "byteOffset" : 2724
340 | },
341 | {
342 | "buffer" : 0,
343 | "byteLength" : 180,
344 | "byteOffset" : 2820
345 | },
346 | {
347 | "buffer" : 0,
348 | "byteLength" : 180,
349 | "byteOffset" : 3000
350 | },
351 | {
352 | "buffer" : 0,
353 | "byteLength" : 120,
354 | "byteOffset" : 3180
355 | },
356 | {
357 | "buffer" : 0,
358 | "byteLength" : 96,
359 | "byteOffset" : 3300
360 | }
361 | ],
362 | "samplers" : [
363 | {
364 | "magFilter" : 9729,
365 | "minFilter" : 9987
366 | }
367 | ],
368 | "buffers" : [
369 | {
370 | "byteLength" : 3396,
371 | "uri" : "TileEdge.bin"
372 | }
373 | ]
374 | }
375 |
--------------------------------------------------------------------------------
/Assets/TileCorner.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "generator" : "Khronos glTF Blender I/O v1.7.33",
4 | "version" : "2.0"
5 | },
6 | "scene" : 0,
7 | "scenes" : [
8 | {
9 | "name" : "Scene",
10 | "nodes" : [
11 | 1
12 | ]
13 | }
14 | ],
15 | "nodes" : [
16 | {
17 | "mesh" : 0,
18 | "name" : "[invisible]CornerCollider"
19 | },
20 | {
21 | "children" : [
22 | 0
23 | ],
24 | "mesh" : 1,
25 | "name" : "[intangible]Corner"
26 | }
27 | ],
28 | "materials" : [
29 | {
30 | "doubleSided" : true,
31 | "name" : "Wall",
32 | "pbrMetallicRoughness" : {
33 | "baseColorTexture" : {
34 | "index" : 0
35 | },
36 | "metallicFactor" : 0,
37 | "roughnessFactor" : 0.4000000059604645
38 | }
39 | },
40 | {
41 | "doubleSided" : true,
42 | "name" : "Ceiling",
43 | "pbrMetallicRoughness" : {
44 | "baseColorTexture" : {
45 | "index" : 1
46 | },
47 | "metallicFactor" : 0,
48 | "roughnessFactor" : 0.5
49 | }
50 | },
51 | {
52 | "doubleSided" : true,
53 | "name" : "Floor",
54 | "pbrMetallicRoughness" : {
55 | "baseColorTexture" : {
56 | "index" : 2
57 | },
58 | "metallicFactor" : 0,
59 | "roughnessFactor" : 0.5
60 | }
61 | }
62 | ],
63 | "meshes" : [
64 | {
65 | "name" : "Cube.007",
66 | "primitives" : [
67 | {
68 | "attributes" : {
69 | "POSITION" : 0,
70 | "NORMAL" : 1,
71 | "TEXCOORD_0" : 2
72 | },
73 | "indices" : 3,
74 | "material" : 0
75 | }
76 | ]
77 | },
78 | {
79 | "name" : "Cube.002",
80 | "primitives" : [
81 | {
82 | "attributes" : {
83 | "POSITION" : 4,
84 | "NORMAL" : 5,
85 | "TEXCOORD_0" : 6
86 | },
87 | "indices" : 7,
88 | "material" : 0
89 | },
90 | {
91 | "attributes" : {
92 | "POSITION" : 8,
93 | "NORMAL" : 9,
94 | "TEXCOORD_0" : 10
95 | },
96 | "indices" : 11,
97 | "material" : 1
98 | },
99 | {
100 | "attributes" : {
101 | "POSITION" : 12,
102 | "NORMAL" : 13,
103 | "TEXCOORD_0" : 14
104 | },
105 | "indices" : 15,
106 | "material" : 2
107 | }
108 | ]
109 | }
110 | ],
111 | "textures" : [
112 | {
113 | "sampler" : 0,
114 | "source" : 0
115 | },
116 | {
117 | "sampler" : 0,
118 | "source" : 1
119 | },
120 | {
121 | "sampler" : 0,
122 | "source" : 2
123 | }
124 | ],
125 | "images" : [
126 | {
127 | "mimeType" : "image/png",
128 | "name" : "Wall",
129 | "uri" : "Wall.png"
130 | },
131 | {
132 | "mimeType" : "image/png",
133 | "name" : "Ceiling",
134 | "uri" : "Ceiling.png"
135 | },
136 | {
137 | "mimeType" : "image/png",
138 | "name" : "Floor",
139 | "uri" : "Floor.png"
140 | }
141 | ],
142 | "accessors" : [
143 | {
144 | "bufferView" : 0,
145 | "componentType" : 5126,
146 | "count" : 21,
147 | "max" : [
148 | 0.5100000500679016,
149 | 2.500000238418579,
150 | 0.5100000500679016
151 | ],
152 | "min" : [
153 | -0.5100000500679016,
154 | 0,
155 | -0.5100000500679016
156 | ],
157 | "type" : "VEC3"
158 | },
159 | {
160 | "bufferView" : 1,
161 | "componentType" : 5126,
162 | "count" : 21,
163 | "type" : "VEC3"
164 | },
165 | {
166 | "bufferView" : 2,
167 | "componentType" : 5126,
168 | "count" : 21,
169 | "type" : "VEC2"
170 | },
171 | {
172 | "bufferView" : 3,
173 | "componentType" : 5123,
174 | "count" : 36,
175 | "type" : "SCALAR"
176 | },
177 | {
178 | "bufferView" : 4,
179 | "componentType" : 5126,
180 | "count" : 45,
181 | "max" : [
182 | 0,
183 | 2.500000238418579,
184 | 0
185 | ],
186 | "min" : [
187 | -0.5000000596046448,
188 | 0,
189 | -0.5000000596046448
190 | ],
191 | "type" : "VEC3"
192 | },
193 | {
194 | "bufferView" : 5,
195 | "componentType" : 5126,
196 | "count" : 45,
197 | "type" : "VEC3"
198 | },
199 | {
200 | "bufferView" : 6,
201 | "componentType" : 5126,
202 | "count" : 45,
203 | "type" : "VEC2"
204 | },
205 | {
206 | "bufferView" : 7,
207 | "componentType" : 5123,
208 | "count" : 192,
209 | "type" : "SCALAR"
210 | },
211 | {
212 | "bufferView" : 8,
213 | "componentType" : 5126,
214 | "count" : 21,
215 | "max" : [
216 | 0.5000000596046448,
217 | 2.500000238418579,
218 | 0.5000000596046448
219 | ],
220 | "min" : [
221 | -0.5000000596046448,
222 | 2.500000238418579,
223 | -0.5000000596046448
224 | ],
225 | "type" : "VEC3"
226 | },
227 | {
228 | "bufferView" : 9,
229 | "componentType" : 5126,
230 | "count" : 21,
231 | "type" : "VEC3"
232 | },
233 | {
234 | "bufferView" : 10,
235 | "componentType" : 5126,
236 | "count" : 21,
237 | "type" : "VEC2"
238 | },
239 | {
240 | "bufferView" : 11,
241 | "componentType" : 5123,
242 | "count" : 72,
243 | "type" : "SCALAR"
244 | },
245 | {
246 | "bufferView" : 12,
247 | "componentType" : 5126,
248 | "count" : 21,
249 | "max" : [
250 | 0.5000000596046448,
251 | 0,
252 | 0.5000000596046448
253 | ],
254 | "min" : [
255 | -0.5000000596046448,
256 | 0,
257 | -0.5000000596046448
258 | ],
259 | "type" : "VEC3"
260 | },
261 | {
262 | "bufferView" : 13,
263 | "componentType" : 5126,
264 | "count" : 21,
265 | "type" : "VEC3"
266 | },
267 | {
268 | "bufferView" : 14,
269 | "componentType" : 5126,
270 | "count" : 21,
271 | "type" : "VEC2"
272 | },
273 | {
274 | "bufferView" : 15,
275 | "componentType" : 5123,
276 | "count" : 72,
277 | "type" : "SCALAR"
278 | }
279 | ],
280 | "bufferViews" : [
281 | {
282 | "buffer" : 0,
283 | "byteLength" : 252,
284 | "byteOffset" : 0
285 | },
286 | {
287 | "buffer" : 0,
288 | "byteLength" : 252,
289 | "byteOffset" : 252
290 | },
291 | {
292 | "buffer" : 0,
293 | "byteLength" : 168,
294 | "byteOffset" : 504
295 | },
296 | {
297 | "buffer" : 0,
298 | "byteLength" : 72,
299 | "byteOffset" : 672
300 | },
301 | {
302 | "buffer" : 0,
303 | "byteLength" : 540,
304 | "byteOffset" : 744
305 | },
306 | {
307 | "buffer" : 0,
308 | "byteLength" : 540,
309 | "byteOffset" : 1284
310 | },
311 | {
312 | "buffer" : 0,
313 | "byteLength" : 360,
314 | "byteOffset" : 1824
315 | },
316 | {
317 | "buffer" : 0,
318 | "byteLength" : 384,
319 | "byteOffset" : 2184
320 | },
321 | {
322 | "buffer" : 0,
323 | "byteLength" : 252,
324 | "byteOffset" : 2568
325 | },
326 | {
327 | "buffer" : 0,
328 | "byteLength" : 252,
329 | "byteOffset" : 2820
330 | },
331 | {
332 | "buffer" : 0,
333 | "byteLength" : 168,
334 | "byteOffset" : 3072
335 | },
336 | {
337 | "buffer" : 0,
338 | "byteLength" : 144,
339 | "byteOffset" : 3240
340 | },
341 | {
342 | "buffer" : 0,
343 | "byteLength" : 252,
344 | "byteOffset" : 3384
345 | },
346 | {
347 | "buffer" : 0,
348 | "byteLength" : 252,
349 | "byteOffset" : 3636
350 | },
351 | {
352 | "buffer" : 0,
353 | "byteLength" : 168,
354 | "byteOffset" : 3888
355 | },
356 | {
357 | "buffer" : 0,
358 | "byteLength" : 144,
359 | "byteOffset" : 4056
360 | }
361 | ],
362 | "samplers" : [
363 | {
364 | "magFilter" : 9729,
365 | "minFilter" : 9987
366 | }
367 | ],
368 | "buffers" : [
369 | {
370 | "byteLength" : 4200,
371 | "uri" : "TileCorner.bin"
372 | }
373 | ]
374 | }
375 |
--------------------------------------------------------------------------------
/Assets/TileKitty.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "generator" : "Khronos glTF Blender I/O v1.7.33",
4 | "version" : "2.0"
5 | },
6 | "scene" : 0,
7 | "scenes" : [
8 | {
9 | "name" : "Scene",
10 | "nodes" : [
11 | 1
12 | ]
13 | }
14 | ],
15 | "nodes" : [
16 | {
17 | "mesh" : 0,
18 | "name" : "[invisible]KittyCollider"
19 | },
20 | {
21 | "children" : [
22 | 0
23 | ],
24 | "mesh" : 1,
25 | "name" : "[intangible]Kitty"
26 | }
27 | ],
28 | "materials" : [
29 | {
30 | "doubleSided" : true,
31 | "name" : "Wall",
32 | "pbrMetallicRoughness" : {
33 | "baseColorTexture" : {
34 | "index" : 0
35 | },
36 | "metallicFactor" : 0,
37 | "roughnessFactor" : 0.4000000059604645
38 | }
39 | },
40 | {
41 | "doubleSided" : true,
42 | "name" : "Ceiling",
43 | "pbrMetallicRoughness" : {
44 | "baseColorTexture" : {
45 | "index" : 1
46 | },
47 | "metallicFactor" : 0,
48 | "roughnessFactor" : 0.5
49 | }
50 | },
51 | {
52 | "doubleSided" : true,
53 | "name" : "Floor",
54 | "pbrMetallicRoughness" : {
55 | "baseColorTexture" : {
56 | "index" : 2
57 | },
58 | "metallicFactor" : 0,
59 | "roughnessFactor" : 0.5
60 | }
61 | }
62 | ],
63 | "meshes" : [
64 | {
65 | "name" : "Cube.011",
66 | "primitives" : [
67 | {
68 | "attributes" : {
69 | "POSITION" : 0,
70 | "NORMAL" : 1,
71 | "TEXCOORD_0" : 2
72 | },
73 | "indices" : 3,
74 | "material" : 0
75 | }
76 | ]
77 | },
78 | {
79 | "name" : "Cube.003",
80 | "primitives" : [
81 | {
82 | "attributes" : {
83 | "POSITION" : 4,
84 | "NORMAL" : 5,
85 | "TEXCOORD_0" : 6
86 | },
87 | "indices" : 7,
88 | "material" : 0
89 | },
90 | {
91 | "attributes" : {
92 | "POSITION" : 8,
93 | "NORMAL" : 9,
94 | "TEXCOORD_0" : 10
95 | },
96 | "indices" : 11,
97 | "material" : 1
98 | },
99 | {
100 | "attributes" : {
101 | "POSITION" : 12,
102 | "NORMAL" : 13,
103 | "TEXCOORD_0" : 14
104 | },
105 | "indices" : 15,
106 | "material" : 2
107 | }
108 | ]
109 | }
110 | ],
111 | "textures" : [
112 | {
113 | "sampler" : 0,
114 | "source" : 0
115 | },
116 | {
117 | "sampler" : 0,
118 | "source" : 1
119 | },
120 | {
121 | "sampler" : 0,
122 | "source" : 2
123 | }
124 | ],
125 | "images" : [
126 | {
127 | "mimeType" : "image/png",
128 | "name" : "Wall",
129 | "uri" : "Wall.png"
130 | },
131 | {
132 | "mimeType" : "image/png",
133 | "name" : "Ceiling",
134 | "uri" : "Ceiling.png"
135 | },
136 | {
137 | "mimeType" : "image/png",
138 | "name" : "Floor",
139 | "uri" : "Floor.png"
140 | }
141 | ],
142 | "accessors" : [
143 | {
144 | "bufferView" : 0,
145 | "componentType" : 5126,
146 | "count" : 32,
147 | "max" : [
148 | 0.5100000500679016,
149 | 2.500000238418579,
150 | 0.5100000500679016
151 | ],
152 | "min" : [
153 | -0.5100000500679016,
154 | 0,
155 | -0.5100000500679016
156 | ],
157 | "type" : "VEC3"
158 | },
159 | {
160 | "bufferView" : 1,
161 | "componentType" : 5126,
162 | "count" : 32,
163 | "type" : "VEC3"
164 | },
165 | {
166 | "bufferView" : 2,
167 | "componentType" : 5126,
168 | "count" : 32,
169 | "type" : "VEC2"
170 | },
171 | {
172 | "bufferView" : 3,
173 | "componentType" : 5123,
174 | "count" : 48,
175 | "type" : "SCALAR"
176 | },
177 | {
178 | "bufferView" : 4,
179 | "componentType" : 5126,
180 | "count" : 90,
181 | "max" : [
182 | 0.5000000596046448,
183 | 2.500000238418579,
184 | 0.5000000596046448
185 | ],
186 | "min" : [
187 | -0.5000000596046448,
188 | 0,
189 | -0.5000000596046448
190 | ],
191 | "type" : "VEC3"
192 | },
193 | {
194 | "bufferView" : 5,
195 | "componentType" : 5126,
196 | "count" : 90,
197 | "type" : "VEC3"
198 | },
199 | {
200 | "bufferView" : 6,
201 | "componentType" : 5126,
202 | "count" : 90,
203 | "type" : "VEC2"
204 | },
205 | {
206 | "bufferView" : 7,
207 | "componentType" : 5123,
208 | "count" : 384,
209 | "type" : "SCALAR"
210 | },
211 | {
212 | "bufferView" : 8,
213 | "componentType" : 5126,
214 | "count" : 18,
215 | "max" : [
216 | 0.5000000596046448,
217 | 2.500000238418579,
218 | 0.5000000596046448
219 | ],
220 | "min" : [
221 | -0.5000000596046448,
222 | 2.500000238418579,
223 | -0.5000000596046448
224 | ],
225 | "type" : "VEC3"
226 | },
227 | {
228 | "bufferView" : 9,
229 | "componentType" : 5126,
230 | "count" : 18,
231 | "type" : "VEC3"
232 | },
233 | {
234 | "bufferView" : 10,
235 | "componentType" : 5126,
236 | "count" : 18,
237 | "type" : "VEC2"
238 | },
239 | {
240 | "bufferView" : 11,
241 | "componentType" : 5123,
242 | "count" : 48,
243 | "type" : "SCALAR"
244 | },
245 | {
246 | "bufferView" : 12,
247 | "componentType" : 5126,
248 | "count" : 18,
249 | "max" : [
250 | 0.5000000596046448,
251 | 0,
252 | 0.5000000596046448
253 | ],
254 | "min" : [
255 | -0.5000000596046448,
256 | 0,
257 | -0.5000000596046448
258 | ],
259 | "type" : "VEC3"
260 | },
261 | {
262 | "bufferView" : 13,
263 | "componentType" : 5126,
264 | "count" : 18,
265 | "type" : "VEC3"
266 | },
267 | {
268 | "bufferView" : 14,
269 | "componentType" : 5126,
270 | "count" : 18,
271 | "type" : "VEC2"
272 | },
273 | {
274 | "bufferView" : 15,
275 | "componentType" : 5123,
276 | "count" : 48,
277 | "type" : "SCALAR"
278 | }
279 | ],
280 | "bufferViews" : [
281 | {
282 | "buffer" : 0,
283 | "byteLength" : 384,
284 | "byteOffset" : 0
285 | },
286 | {
287 | "buffer" : 0,
288 | "byteLength" : 384,
289 | "byteOffset" : 384
290 | },
291 | {
292 | "buffer" : 0,
293 | "byteLength" : 256,
294 | "byteOffset" : 768
295 | },
296 | {
297 | "buffer" : 0,
298 | "byteLength" : 96,
299 | "byteOffset" : 1024
300 | },
301 | {
302 | "buffer" : 0,
303 | "byteLength" : 1080,
304 | "byteOffset" : 1120
305 | },
306 | {
307 | "buffer" : 0,
308 | "byteLength" : 1080,
309 | "byteOffset" : 2200
310 | },
311 | {
312 | "buffer" : 0,
313 | "byteLength" : 720,
314 | "byteOffset" : 3280
315 | },
316 | {
317 | "buffer" : 0,
318 | "byteLength" : 768,
319 | "byteOffset" : 4000
320 | },
321 | {
322 | "buffer" : 0,
323 | "byteLength" : 216,
324 | "byteOffset" : 4768
325 | },
326 | {
327 | "buffer" : 0,
328 | "byteLength" : 216,
329 | "byteOffset" : 4984
330 | },
331 | {
332 | "buffer" : 0,
333 | "byteLength" : 144,
334 | "byteOffset" : 5200
335 | },
336 | {
337 | "buffer" : 0,
338 | "byteLength" : 96,
339 | "byteOffset" : 5344
340 | },
341 | {
342 | "buffer" : 0,
343 | "byteLength" : 216,
344 | "byteOffset" : 5440
345 | },
346 | {
347 | "buffer" : 0,
348 | "byteLength" : 216,
349 | "byteOffset" : 5656
350 | },
351 | {
352 | "buffer" : 0,
353 | "byteLength" : 144,
354 | "byteOffset" : 5872
355 | },
356 | {
357 | "buffer" : 0,
358 | "byteLength" : 96,
359 | "byteOffset" : 6016
360 | }
361 | ],
362 | "samplers" : [
363 | {
364 | "magFilter" : 9729,
365 | "minFilter" : 9987
366 | }
367 | ],
368 | "buffers" : [
369 | {
370 | "byteLength" : 6112,
371 | "uri" : "TileKitty.bin"
372 | }
373 | ]
374 | }
375 |
--------------------------------------------------------------------------------
/BakedScene.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System;
3 | using System.Threading.Tasks;
4 |
5 | namespace StereoKit.Framework
6 | {
7 | public class BakedScene
8 | {
9 | List _lights = new List();
10 | BakedSceneItem[] _items;
11 | StaticScene _scene;
12 | SphericalHarmonics _ambient;
13 | SphericalHarmonics _sky;
14 | int _bounceSamples;
15 |
16 | public bool Baking { get; private set; }
17 | public float BakingProgress { get; private set; }
18 | public float LightCutoff { get; set; } = 1/255.0f;
19 |
20 | public BakedScene() { }
21 |
22 | public void AddPointLight (Vec3 at, Color color, float intensity) { _lights.Add(new BakeLight(at, color, intensity, false)); }
23 | public void AddDirectionalLight(Vec3 dir, Color color, float intensity) { _lights.Add(new BakeLight(-dir.Normalized, color, intensity, true)); }
24 | public void SetAmbient (SphericalHarmonics ambient) => _ambient = ambient;
25 | public void SetSky (SphericalHarmonics sky) => _sky = sky;
26 |
27 | public void ClearLights() => _lights.Clear();
28 |
29 | public void Bake(StaticScene scene, int bounceSamples = 0, bool areaLights = true)
30 | {
31 | _bounceSamples = bounceSamples;
32 | _scene = scene;
33 | Baking = true;
34 | BakingProgress = 0;
35 |
36 | long totalVerts = 0;
37 | long currVerts = 0;
38 |
39 | Dictionary vertexCache = new Dictionary();
40 | Dictionary indexCache = new Dictionary();
41 | Dictionary textureMaterials = new Dictionary();
42 |
43 | // Build our list of mesh/material pairs
44 | List itemList = new List();
45 | for (int i = 0; i < scene._items.Count; i++)
46 | {
47 | if (!scene._items[i].visible) continue;
48 | Tex tex = scene._items[i].material.GetTexture("diffuse");
49 | if (!textureMaterials.TryGetValue(tex.Id, out Material mat))
50 | {
51 | mat = Material.Unlit.Copy();
52 | mat[MatParamName.DiffuseTex] = tex;
53 | textureMaterials[tex.Id] = mat;
54 | }
55 |
56 | int item = itemList.FindIndex(t => t.material == mat);
57 | if (item == -1)
58 | {
59 | BakedSceneItem sceneItem = new BakedSceneItem();
60 | sceneItem.material = mat;
61 | itemList.Add(sceneItem);
62 | }
63 |
64 | // cache mesh data while we're at it
65 | if (!vertexCache.TryGetValue(scene._items[i].mesh, out Vertex[] meshVerts))
66 | {
67 | meshVerts = scene._items[i].mesh.GetVerts();
68 | vertexCache[scene._items[i].mesh] = meshVerts;
69 | indexCache [scene._items[i].mesh] = scene._items[i].mesh.GetInds();
70 | }
71 | }
72 | BakedSceneItem[] itemArray = itemList.ToArray();
73 |
74 | // allocate memory for the baked verts
75 | for (int i = 0; i < scene._items.Count; i++)
76 | {
77 | if (!scene._items[i].visible) continue;
78 |
79 | Tex tex = scene._items[i].material.GetTexture("diffuse");
80 | Material mat = textureMaterials[tex.Id];
81 |
82 | int item = Array.FindIndex(itemArray,t => t.material == mat);
83 | itemArray[item].vertCount += scene._items[i].mesh.VertCount;
84 | itemArray[item].indCount += scene._items[i].mesh.IndCount;
85 | }
86 | for (int i = 0; i t.material == mat);
104 | Vertex[] meshVerts = vertexCache[scene._items[i].mesh];
105 |
106 | BakeMesh(vertexCache[scene._items[i].mesh], itemArray[item].verts, itemArray[item].vertCurr, scene._items[i].transform, areaLights);
107 |
108 | uint[] meshInds = indexCache[scene._items[i].mesh];
109 | for (int t = 0; t < meshInds.Length; t++)
110 | itemArray[item].inds[itemArray[item].indCurr + t] = meshInds[t] + itemArray[item].vertCurr;
111 |
112 | itemArray[item].indCurr += (uint)meshInds .Length;
113 | itemArray[item].vertCurr += (uint)meshVerts.Length;
114 |
115 | currVerts += meshVerts.Length;
116 | BakingProgress = (float)(currVerts / (double)totalVerts);
117 | }
118 |
119 | // And generate the meshes
120 | for (int i = 0; i < itemArray.Length; i++)
121 | {
122 | itemArray[i].mesh = new Mesh();
123 | itemArray[i].mesh.SetVerts(itemArray[i].verts);
124 | itemArray[i].mesh.SetInds (itemArray[i].inds);
125 | itemArray[i].verts = null;
126 | itemArray[i].inds = null;
127 | }
128 |
129 | _items = itemArray;
130 | Baking = false;
131 | BakingProgress = 1;
132 | }
133 |
134 | private void BakeMesh(Vertex[] verts, Vertex[] to, uint toOffset, Matrix at, bool areaLights)
135 | {
136 | //for (int v = 0; v < verts.Length; v++)
137 | Parallel.For(0, verts.Length, (v) =>
138 | {
139 | Vertex vert = verts[v];
140 | vert.pos = at.Transform(vert.pos);
141 | vert.norm = at.TransformNormal(vert.norm).Normalized;
142 |
143 | Color amb = _ambient.Sample(vert.norm);
144 | Color c = SamplePoint(vert.pos, vert.norm, _bounceSamples, areaLights);
145 | c.r += amb.r;
146 | c.g += amb.g;
147 | c.b += amb.b;
148 |
149 | if (c.r > 1) c.r = 1;
150 | if (c.g > 1) c.g = 1;
151 | if (c.b > 1) c.b = 1;
152 | vert.col = c;
153 |
154 | to[v + toOffset] = vert;
155 | }
156 | );
157 | }
158 |
159 | /*Vec2[] lightSampleOffsets = new Vec2[] {
160 | new Vec2( 0, 0),
161 | new Vec2(-1, 1),
162 | new Vec2( 1, 1),
163 | new Vec2(-1,-1),
164 | new Vec2( 1,-1),
165 | };*/
166 | /*Vec2[] lightSampleOffsets = new Vec2[] {
167 | new Vec2( .25f, .97f),
168 | new Vec2( .71f,-.71f),
169 | new Vec2(-.97f,-.26f),
170 | };*/
171 | /*Vec2[] lightSampleOffsets = new Vec2[] {
172 | new Vec2( .34f, .94f),
173 | new Vec2( .64f,-.76f),
174 | new Vec2(-.98f,-.17f),
175 | };*/
176 | Vec2[] lightSampleOffsets = new Vec2[] {
177 | new Vec2(-.42f, .9f),
178 | new Vec2( .9f, .42f),
179 | new Vec2( .42f,-.9f),
180 | new Vec2(-.9f, -.42f),
181 | };
182 | private float LightVisibility(Vec3 lightPos, Vec3 from, float checkSize, bool smoothed)
183 | {
184 | if (!smoothed)
185 | {
186 | Vec3 directDir = lightPos - from;
187 | return _scene.Raycast(new Ray(from, directDir), out Ray hit) && Vec3.DistanceSq(from, hit.position) < directDir.MagnitudeSq
188 | ? 0
189 | : 1;
190 | }
191 |
192 | Vec3 dir = (lightPos - from).Normalized;
193 | Vec3 right = Vec3.PerpendicularRight(dir, Vec3.Up);
194 | Vec3 up = -Vec3.PerpendicularRight(dir, right);
195 |
196 | float coverage = 0;
197 | int count = smoothed ? lightSampleOffsets.Length : 1;
198 | for (int i = 0; i < count; i++)
199 | {
200 | Vec3 currLight = lightPos +
201 | lightSampleOffsets[i].x * right * checkSize +
202 | lightSampleOffsets[i].y * up * checkSize;
203 | Vec3 currDir = currLight - from;
204 |
205 | float distSq = 100000000;
206 | if (_scene.Raycast(new Ray(from, currDir), out Ray hit))
207 | {
208 | distSq = Vec3.DistanceSq(from, hit.position);
209 | }
210 |
211 | if (distSq + 0.01f > currDir.MagnitudeSq)
212 | coverage += 1;
213 | }
214 |
215 | return (coverage / count);
216 | }
217 |
218 | bool debug = false;
219 |
220 | static Vec3 Quantize(Vec3 v, float by)
221 | {
222 | return new Vec3(
223 | (int)(v.x * by) / by,
224 | (int)(v.y * by) / by,
225 | (int)(v.z * by) / by);
226 | }
227 |
228 | private Color SamplePoint(Vec3 at, Vec3 norm, int bounceSamples, bool areaLights)
229 | {
230 | // Offset the position from the surface, just a bit
231 | at += norm * 0.01f;
232 |
233 | // Quantize the position to help remove small variations in
234 | // lighting from one vertex to the next
235 | at = Quantize(at, 200);
236 | norm = Quantize(norm, 200);
237 |
238 | Noise.NextSeed = new Noise.Seed { seed = (uint)(at.x * 1017 + at.y * 37000 + at.z * 12789) };
239 |
240 | Color c = new Color(0, 0, 0, 1);
241 | for (int i = 0; i < _lights.Count; i++)
242 | {
243 | Color lc = _lights[i].color;
244 | float vis = 0;
245 | if (_lights[i].directional)
246 | {
247 | vis = LightVisibility(at + _lights[i].pos * 1000.0f, at, 100.0f, areaLights);
248 | }
249 | else
250 | {
251 | Vec3 dir = _lights[i].pos - at;
252 | float magSq = dir.MagnitudeSq;
253 | float intensity = (1.0f / magSq) * _lights[i].intensity * Math.Max(0, Vec3.Dot(dir/SKMath.Sqrt(magSq), norm));
254 | // Skip the light if we know it's not bright enough early!
255 | if (intensity > LightCutoff)
256 | vis = LightVisibility(_lights[i].pos, at, 0.3f, areaLights) * intensity;
257 | }
258 | c = new Color(c.r + lc.r * vis, c.g + lc.g * vis, c.b + lc.b * vis, c.a);
259 | }
260 |
261 | if (debug) Mesh.Sphere.Draw(Material.Unlit, Matrix.TS(at, 0.2f), c);
262 |
263 | Vec3 right = Vec3.PerpendicularRight(norm, new Vec3(0, 1, -1.003f)).Normalized;
264 | Vec3 up = Vec3.PerpendicularRight(right, norm).Normalized;
265 | float mod = (1.0f / bounceSamples);
266 | for (int i=0;i> 16);
287 | b = ((b & 0x55555555) << 1) | ((b & 0xAAAAAAAA) >> 1);
288 | b = ((b & 0x33333333) << 2) | ((b & 0xCCCCCCCC) >> 2);
289 | b = ((b & 0x0F0F0F0F) << 4) | ((b & 0xF0F0F0F0) >> 4);
290 | b = ((b & 0x00FF00FF) << 8) | ((b & 0xFF00FF00) >> 8);
291 |
292 | float radicalInverseVDC = b * 2.3283064365386963e-10f;
293 | return new Vec2((i / (float)numSamples), radicalInverseVDC);
294 | }
295 |
296 | Vec3 SampleHemisphere_Uniform(uint i, uint numSamples)
297 | {
298 | // Returns a 3D sample vector orientated around (0.0, 1.0, 0.0)
299 | // For practical use, must rotate with a rotation matrix (or whatever
300 | // your preferred approach is) for use with normals, etc.
301 |
302 | Vec2 xi = Hammersley(i, numSamples);
303 |
304 | float phi = xi.y * 2.0f * (float)Math.PI;
305 | float cosTheta = 1.0f - xi.x;
306 | float sinTheta = SKMath.Sqrt(1.0f - cosTheta * cosTheta);
307 |
308 | return new Vec3(SKMath.Cos(phi) * sinTheta, cosTheta, SKMath.Sin(phi) * sinTheta);
309 | }
310 |
311 | public bool Raycast(Ray worldRay, out Ray at)
312 | => _scene.Raycast(worldRay, out at);
313 |
314 | public void Draw()
315 | {
316 | if (_items != null)
317 | {
318 | for (int i = 0; i < _items.Length; i++)
319 | _items[i].Draw();
320 | }
321 | else if (_scene != null)
322 | {
323 | _scene.Draw();
324 | }
325 | }
326 |
327 | public void DrawDebug()
328 | {
329 | for (int i = 0; i < _lights.Count; i++)
330 | {
331 | if (_lights[i].directional) continue;
332 | Mesh.Sphere.Draw(Material.Unlit, Matrix.TS(_lights[i].pos, 0.1f), _lights[i].color);
333 | }
334 |
335 | if (Input.Key(Key.Space).IsActive() && _scene.Raycast(Input.Pointer(0, InputSource.HandRight).ray, out Ray hit))
336 | {
337 | debug = true;
338 | SamplePoint(hit.position, hit.direction, _bounceSamples, true);
339 | debug = false;
340 | }
341 | if (Input.Key(Key.F).IsJustActive())
342 | {
343 | for (int i = 0; i < _items.Length; i++)
344 | _items[i].material.Wireframe = true;
345 | }
346 | if (Input.Key(Key.F).IsJustInactive())
347 | {
348 | for (int i = 0; i < _items.Length; i++)
349 | _items[i].material.Wireframe = false;
350 | }
351 | }
352 | }
353 |
354 | struct BakedSceneItem
355 | {
356 | internal Mesh mesh;
357 | internal Material material;
358 |
359 | internal Vertex[] verts;
360 | internal uint [] inds;
361 | internal int vertCount;
362 | internal int indCount;
363 | internal uint vertCurr;
364 | internal uint indCurr;
365 |
366 | public void Draw() => mesh.Draw(material, Matrix.Identity);
367 | }
368 |
369 | struct BakeLight
370 | {
371 | internal Vec3 pos;
372 | internal Color color;
373 | internal float intensity;
374 | internal bool directional;
375 |
376 | public BakeLight(Vec3 pos, Color color, float intensity, bool directional) { this.pos = pos; this.color = color; this.intensity = intensity; this.directional = directional; }
377 | }
378 | }
379 |
--------------------------------------------------------------------------------