-
Notifications
You must be signed in to change notification settings - Fork 4
/
Program.cs
141 lines (103 loc) · 3.94 KB
/
Program.cs
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using Avalonia.Threading;
using GShark.Geometry;
namespace example;
// example-0006
// draw nurb surface
//
// - ctrl+w to toggle ShadeWithEdge
// - application 'space' key to toggle normal calc type
// - n key to toggle normals visiblity
// - application 'ctrl+space' key to toggle animation through objectmatrix
class Program
{
static void Main(string[] args)
{
InitAvalonia();
var w = GLWindow.Create(
onFocusedControlChanged: (split, AvaloniaGLControl, isInitial) =>
{
if (isInitial)
{
// load view from the layout.json file (copied by the csproj)
split.LoadViewLayout();
}
}
);
bool computeNurbNormals = true;
GLTriangleFigure? triFig = null;
w.GLModel.BuildModel = (glCtl, isInitial) =>
{
if (!isInitial) return;
var glModel = glCtl.GLModel;
glModel.Clear();
var plateCenterRef = new Vector3(5, 5, -5);
var color = Color.FromArgb(68, 97, 147);
var nurb = NurbsSurface.FromCorners(
new Point3(0, 0, 0),
new Point3(10, 0, 0),
new Point3(10, 10, 15),
new Point3(0, 10, -4));
var tris = nurb.NurbToGL(color);
// build figure from nurb mesh
triFig = new GLTriangleFigure(tris);
triFig.SetupComputeNormal(mean: computeNurbNormals);
glModel.AddFigure(triFig);
glModel.PointLights.Add(new GLPointLight(new Vector3(7, 8, 14)));
};
Task? task = null;
bool taskPause = false; // var to trigger anim
var are = new AutoResetEvent(false); // thread blocker var
w.KeyDown += (sender, e) =>
{
var glCtl = w.FocusedControl;
if (glCtl is null) return;
var glModel = glCtl.GLModel;
if (new KeyGesture(Key.Space, KeyModifiers.Control).Matches(e))
{
if (task is not null)
{
taskPause = !taskPause;
are.Set(); // unlock are.WaitOne()
return;
}
task = Task.Run(async () =>
{
var angle = 0f;
var angleIncrement_rad = (float)2.5d.ToRad();
while (true)
{
if (taskPause)
{
are.WaitOne(); // waiting till are.Set()
}
// access to UI thread through Dispatcher.UIThread
// because calling from non ui thread
await Dispatcher.UIThread.InvokeAsync(() =>
{
var m =
Matrix4x4.CreateTranslation(-glModel.LBBox.Middle)
*
Matrix4x4.CreateRotationZ(angle)
*
Matrix4x4.CreateTranslation(glModel.LBBox.Middle);
foreach (var fig in glModel.Figures)
fig.ObjectMatrix = m;
angle += angleIncrement_rad;
glCtl.InvalidateAll();
});
await Task.Delay(50);
}
});
}
if (e.Key == Key.Space)
{
computeNurbNormals = !computeNurbNormals;
if (triFig is not null)
triFig.SetupComputeNormal(mean: computeNurbNormals);
// note : there is no need to rebuild the model, invalidate will use updated vertex normals
glCtl.InvalidateAll();
}
};
w.ShowSync();
}
}