-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathgl_lines.cs
164 lines (149 loc) · 6.12 KB
/
gl_lines.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using System;
namespace principia {
namespace ksp_plugin_adapter {
internal static class GLLines {
public enum Style {
Solid,
Dashed,
Faded,
}
public static void Draw(Action line_vertices) {
try {
UnityEngine.GL.PushMatrix();
line_material.SetPass(0);
UnityEngine.GL.LoadPixelMatrix();
UnityEngine.GL.Begin(UnityEngine.GL.LINES);
line_vertices();
UnityEngine.GL.End();
UnityEngine.GL.PopMatrix();
} catch (Exception e) {
Log.Fatal("Exception while drawing lines: " + e);
}
}
public static void AddSegment(Vector3d world_begin,
Vector3d world_end) {
UnityEngine.Vector3 begin = WorldToMapScreen(world_begin);
UnityEngine.Vector3 end = WorldToMapScreen(world_end);
if (begin.z > 0 && end.z > 0) {
UnityEngine.GL.Vertex3(begin.x, begin.y, 0);
UnityEngine.GL.Vertex3(end.x, end.y, 0);
}
}
public static DisposablePlanetarium NewPlanetarium(IntPtr plugin,
XYZ sun_world_position) {
UnityEngine.Camera camera = PlanetariumCamera.Camera;
UnityEngine.Vector3 opengl_camera_x_in_world =
camera.cameraToWorldMatrix.MultiplyVector(
new UnityEngine.Vector3(1, 0, 0));
UnityEngine.Vector3 opengl_camera_y_in_world =
camera.cameraToWorldMatrix.MultiplyVector(
new UnityEngine.Vector3(0, 1, 0));
UnityEngine.Vector3 opengl_camera_z_in_world =
camera.cameraToWorldMatrix.MultiplyVector(
new UnityEngine.Vector3(0, 0, 1));
UnityEngine.Vector3 camera_position_in_world =
ScaledSpace.ScaledToLocalSpace(camera.transform.position);
// For explanations regarding the OpenGL projection matrix, see
// http://www.songho.ca/opengl/gl_projectionmatrix.html. The on-centre
// projection matrix has the form:
// n / w 0 0 0
// 0 n / h 0 0
// 0 0 (n + f) / (n - f) 2 f n / (n - f)
// 0 0 -1 0
// where n and f are the near- and far-clipping distances, and w and h
// are the half-width and half-height of the screen seen in the focal plane.
// n is also the focal distance, but we prefer to make that distance 1 metre
// to avoid having to rescale the result. The only actual effect of n is
// the clipping distance, and in space, no one can hear you clip.
double m00 = camera.projectionMatrix[0, 0];
double m11 = camera.projectionMatrix[1, 1];
double field_of_view = Math.Atan2(Math.Sqrt(m00 * m00 + m11 * m11),
m00 * m11);
return plugin.PlanetariumCreate(
sun_world_position,
(XYZ)(Vector3d)opengl_camera_x_in_world,
(XYZ)(Vector3d)opengl_camera_y_in_world,
(XYZ)(Vector3d)opengl_camera_z_in_world,
(XYZ)(Vector3d)camera_position_in_world,
/*focal=*/1,
field_of_view);
}
public static void PlotRP2Lines(DisposableIterator rp2_lines_iterator,
UnityEngine.Color colour,
Style style) {
UnityEngine.GL.Color(colour);
// First evaluate the total size of the lines.
int size = 0;
for (;
!rp2_lines_iterator.IteratorAtEnd();
rp2_lines_iterator.IteratorIncrement()) {
using (DisposableIterator rp2_line_iterator =
rp2_lines_iterator.IteratorGetRP2LinesIterator()) {
size += rp2_line_iterator.IteratorSize();
}
}
// Reset the iterator and do the actual plotting.
rp2_lines_iterator.IteratorReset();
int index = 0;
for (;
!rp2_lines_iterator.IteratorAtEnd();
rp2_lines_iterator.IteratorIncrement()) {
using (DisposableIterator rp2_line_iterator =
rp2_lines_iterator.IteratorGetRP2LinesIterator()) {
XY? previous_rp2_point = null;
for (;
!rp2_line_iterator.IteratorAtEnd();
rp2_line_iterator.IteratorIncrement()) {
XY current_rp2_point = ToScreen(
rp2_line_iterator.IteratorGetRP2LineXY());
if (previous_rp2_point.HasValue) {
if (style == Style.Faded) {
var faded_colour = colour;
// Fade from the opacity of |colour| (when index = 0) down to 1/4
// of that opacity.
faded_colour.a *= 1 - (float)(4 * index) / (float)(5 * size);
UnityEngine.GL.Color(faded_colour);
}
if (style != Style.Dashed || index % 2 == 1) {
UnityEngine.GL.Vertex3((float)previous_rp2_point.Value.x,
(float)previous_rp2_point.Value.y,
0);
UnityEngine.GL.Vertex3((float)current_rp2_point.x,
(float)current_rp2_point.y,
0);
}
}
previous_rp2_point = current_rp2_point;
++index;
}
}
}
}
private static UnityEngine.Vector3 WorldToMapScreen(Vector3d world) {
return PlanetariumCamera.Camera.WorldToScreenPoint(
ScaledSpace.LocalToScaledSpace(world));
}
private static XY ToScreen(XY rp2_point) {
UnityEngine.Camera camera = PlanetariumCamera.Camera;
return new XY{x = (rp2_point.x * camera.projectionMatrix[0, 0] + 1.0) *
0.5 * camera.pixelWidth,
y = (rp2_point.y * camera.projectionMatrix[1, 1] + 1.0) *
0.5 * camera.pixelHeight};
}
private static UnityEngine.Material line_material_;
private static UnityEngine.Material line_material {
get {
if (line_material_ == null) {
line_material_ = new UnityEngine.Material(
#if KSP_VERSION_1_10_1
UnityEngine.Shader.Find("KSP/Particles/Additive"));
#elif KSP_VERSION_1_7_3
UnityEngine.Shader.Find("Particles/Additive"));
#endif
}
return line_material_;
}
}
}
} // namespace ksp_plugin_adapter
} // namespace principia