diff --git a/BuildTime.txt b/BuildTime.txt index b9b1431..d17b050 100644 --- a/BuildTime.txt +++ b/BuildTime.txt @@ -1 +1 @@ -2026-04-03 21:32:07 \ No newline at end of file +2026-04-03 22:07:05 \ No newline at end of file diff --git a/GitCommit.txt b/GitCommit.txt index ac1ebf7..d4958c4 100644 --- a/GitCommit.txt +++ b/GitCommit.txt @@ -1 +1 @@ -1d41885 \ No newline at end of file +395df7b \ No newline at end of file diff --git a/Gui/Apps/DemoLauncher.cs b/Gui/Apps/DemoLauncher.cs index 5a4529e..af176e8 100644 --- a/Gui/Apps/DemoLauncher.cs +++ b/Gui/Apps/DemoLauncher.cs @@ -48,6 +48,8 @@ namespace CMLeonOS.Gui.Apps { new AppMetadata("Starfield", () => { return new Apps.Demos.Starfield(); }, Icons.Icon_Starfield, Color.Black ), new AppMetadata("Mandelbrot", () => { return new Apps.Demos.Mandelbrot(); }, Icons.Icon_Mandelbrot, Color.Black ), + new AppMetadata("Cube3D (OSGD)", () => { return new Apps.Demos.Cube3D(); }, AppManager.DefaultAppIcon, Color.Black ), + new AppMetadata("Pyramid3D (OSGD)", () => { return new Apps.Demos.Pyramid3D(); }, AppManager.DefaultAppIcon, Color.Black ), }; private const string message = "Demo Launcher"; diff --git a/Gui/Apps/Demos/Cube3D.cs b/Gui/Apps/Demos/Cube3D.cs new file mode 100644 index 0000000..6969a45 --- /dev/null +++ b/Gui/Apps/Demos/Cube3D.cs @@ -0,0 +1,86 @@ +using CMLeonOS; +using CMLeonOS.Gui.UILib; +using CMLeonOS.OSGraphicDraw; +using System.Drawing; + +namespace CMLeonOS.Gui.Apps.Demos +{ + internal class Cube3D : Process + { + internal Cube3D() : base("Cube3D", ProcessType.Application) { } + + private readonly WindowManager wm = ProcessManager.GetProcess(); + private AppWindow window; + + private double angleX = 0d; + private double angleY = 0d; + private double angleZ = 0d; + + private static readonly Vec3[] BaseVertices = new Vec3[] + { + new Vec3(-1, -1, -1), + new Vec3( 1, -1, -1), + new Vec3( 1, 1, -1), + new Vec3(-1, 1, -1), + new Vec3(-1, -1, 1), + new Vec3( 1, -1, 1), + new Vec3( 1, 1, 1), + new Vec3(-1, 1, 1), + }; + + private static readonly int[] Edges = new int[] + { + 0,1, 1,2, 2,3, 3,0, + 4,5, 5,6, 6,7, 7,4, + 0,4, 1,5, 2,6, 3,7 + }; + + private void RenderCube() + { + window.Clear(Color.FromArgb(15, 17, 24)); + + Vec3[] transformed = new Vec3[BaseVertices.Length]; + for (int i = 0; i < BaseVertices.Length; i++) + { + Vec3 v = BaseVertices[i]; + v = Vec3.RotateX(v, angleX); + v = Vec3.RotateY(v, angleY); + v = Vec3.RotateZ(v, angleZ); + transformed[i] = v; + } + + double fovScale = 240d; + double cameraDistance = 4.2d; + + for (int i = 0; i < Edges.Length; i += 2) + { + int a = Edges[i]; + int b = Edges[i + 1]; + Renderer3D.DrawLine3D(window, transformed[a], transformed[b], Color.FromArgb(188, 224, 255), fovScale, cameraDistance); + } + + window.DrawString("OSGD Cube Demo", Color.FromArgb(140, 170, 198), 10, 8); + wm.Update(window); + } + + public override void Start() + { + base.Start(); + window = new AppWindow(this, 280, 140, 480, 360); + window.Title = "Cube3D"; + window.CanResize = true; + window.Closing = TryStop; + wm.AddWindow(window); + + RenderCube(); + } + + public override void Run() + { + angleX += 0.015d; + angleY += 0.019d; + angleZ += 0.011d; + RenderCube(); + } + } +} diff --git a/Gui/Apps/Demos/Pyramid3D.cs b/Gui/Apps/Demos/Pyramid3D.cs new file mode 100644 index 0000000..f86d4bf --- /dev/null +++ b/Gui/Apps/Demos/Pyramid3D.cs @@ -0,0 +1,85 @@ +using CMLeonOS; +using CMLeonOS.Gui.UILib; +using CMLeonOS.OSGraphicDraw; +using System.Drawing; + +namespace CMLeonOS.Gui.Apps.Demos +{ + internal class Pyramid3D : Process + { + internal Pyramid3D() : base("Pyramid3D", ProcessType.Application) { } + + private readonly WindowManager wm = ProcessManager.GetProcess(); + private AppWindow window; + + private double angleX = 0d; + private double angleY = 0d; + private double angleZ = 0d; + + // Base square + apex + private static readonly Vec3[] BaseVertices = new Vec3[] + { + new Vec3(-1, -1, -1), + new Vec3( 1, -1, -1), + new Vec3( 1, -1, 1), + new Vec3(-1, -1, 1), + new Vec3( 0, 1, 0), // apex + }; + + // edges in pairs + private static readonly int[] Edges = new int[] + { + 0,1, 1,2, 2,3, 3,0, + 0,4, 1,4, 2,4, 3,4 + }; + + private void RenderPyramid() + { + window.Clear(Color.FromArgb(14, 18, 22)); + + Vec3[] transformed = new Vec3[BaseVertices.Length]; + for (int i = 0; i < BaseVertices.Length; i++) + { + Vec3 v = BaseVertices[i]; + v = Vec3.RotateX(v, angleX); + v = Vec3.RotateY(v, angleY); + v = Vec3.RotateZ(v, angleZ); + transformed[i] = v; + } + + double fovScale = 230d; + double cameraDistance = 4.0d; + Color wireColor = Color.FromArgb(255, 208, 136); + + for (int i = 0; i < Edges.Length; i += 2) + { + int a = Edges[i]; + int b = Edges[i + 1]; + Renderer3D.DrawLine3D(window, transformed[a], transformed[b], wireColor, fovScale, cameraDistance); + } + + window.DrawString("OSGD Pyramid Demo", Color.FromArgb(176, 184, 196), 10, 8); + wm.Update(window); + } + + public override void Start() + { + base.Start(); + window = new AppWindow(this, 300, 160, 460, 340); + window.Title = "Pyramid3D"; + window.CanResize = true; + window.Closing = TryStop; + wm.AddWindow(window); + + RenderPyramid(); + } + + public override void Run() + { + angleX += 0.014d; + angleY += 0.017d; + angleZ += 0.010d; + RenderPyramid(); + } + } +} diff --git a/OSGraphicDraw/Renderer3D.cs b/OSGraphicDraw/Renderer3D.cs new file mode 100644 index 0000000..2007900 --- /dev/null +++ b/OSGraphicDraw/Renderer3D.cs @@ -0,0 +1,38 @@ +using CMLeonOS.Gui; +using System.Drawing; + +namespace CMLeonOS.OSGraphicDraw +{ + internal static class Renderer3D + { + internal static bool Project(Vec3 p, int width, int height, double fovScale, double cameraDistance, out int sx, out int sy) + { + double z = p.Z + cameraDistance; + if (z <= 0.05d) + { + sx = 0; + sy = 0; + return false; + } + + double inv = fovScale / z; + sx = (int)((p.X * inv) + (width / 2.0)); + sy = (int)((-p.Y * inv) + (height / 2.0)); + return true; + } + + internal static void DrawLine3D(Window target, Vec3 a, Vec3 b, Color color, double fovScale, double cameraDistance) + { + if (!Project(a, target.Width, target.Height, fovScale, cameraDistance, out int ax, out int ay)) + { + return; + } + if (!Project(b, target.Width, target.Height, fovScale, cameraDistance, out int bx, out int by)) + { + return; + } + + target.DrawLine(ax, ay, bx, by, color); + } + } +} diff --git a/OSGraphicDraw/Vec3.cs b/OSGraphicDraw/Vec3.cs new file mode 100644 index 0000000..4ba16c1 --- /dev/null +++ b/OSGraphicDraw/Vec3.cs @@ -0,0 +1,39 @@ +using System; + +namespace CMLeonOS.OSGraphicDraw +{ + internal struct Vec3 + { + internal double X; + internal double Y; + internal double Z; + + internal Vec3(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } + + internal static Vec3 RotateX(Vec3 v, double radians) + { + double c = Math.Cos(radians); + double s = Math.Sin(radians); + return new Vec3(v.X, (v.Y * c) - (v.Z * s), (v.Y * s) + (v.Z * c)); + } + + internal static Vec3 RotateY(Vec3 v, double radians) + { + double c = Math.Cos(radians); + double s = Math.Sin(radians); + return new Vec3((v.X * c) + (v.Z * s), v.Y, (-v.X * s) + (v.Z * c)); + } + + internal static Vec3 RotateZ(Vec3 v, double radians) + { + double c = Math.Cos(radians); + double s = Math.Sin(radians); + return new Vec3((v.X * c) - (v.Y * s), (v.X * s) + (v.Y * c), v.Z); + } + } +}