-
Notifications
You must be signed in to change notification settings - Fork 115
/
GLTools.cs
executable file
·225 lines (199 loc) · 8.64 KB
/
GLTools.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
* Kopernicus Planetary System Modifier
* -------------------------------------------------------------
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* This library is intended to be used as a plugin for Kerbal Space Program
* which is copyright 2011-2017 Squad. Your usage of Kerbal Space Program
* itself is governed by the terms of its EULA, not the license above.
*
* https://kerbalspaceprogram.com
*/
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Kopernicus
{
namespace Components
{
/// <summary>
/// Utility for drawing GL lines
/// </summary>
public static class GLTools
{
/// <summary>
/// Possibilities for styling a GL line
/// </summary>
public enum Style
{
SOLID = 1,
DASHED = 2
}
/// <summary>
/// The resolution of the gl line
/// </summary>
public const Double resolution = 1d;
/// <summary>
/// The internal representation of the GL material
/// </summary>
private static Material _material;
/// <summary>
/// The screen points
/// </summary>
private static Vector3 screenPoint1, screenPoint2;
/// <summary>
/// A list with vertices for the GL Line
/// </summary>
private static List<Vector3d> points = new List<Vector3d>();
/// <summary>
/// Gets or sets the used GL material.
/// </summary>
/// <value>
/// The material.
/// </value>
public static Material material
{
get
{
if (_material == null)
_material = new Material(Shader.Find("Particles/Additive"));
return _material;
}
set { _material = material; }
}
/// <summary>
/// Draws the orbit with the given arguments.
/// </summary>
public static void DrawOrbit(Double inc, Double e, Double sma, Double lan, Double w, Double mEp, Double t, CelestialBody body)
{
DrawOrbit(new Orbit(inc, e, sma, lan, w, mEp, t, body));
}
/// <summary>
/// Draws the orbit with the given arguments.
/// </summary>
public static void DrawOrbit(Double inc, Double e, Double sma, Double lan, Double w, Double mEp, Double t, CelestialBody body, Color color)
{
DrawOrbit(new Orbit(inc, e, sma, lan, w, mEp, t, body), color);
}
/// <summary>
/// Draws the orbit with the given arguments.
/// </summary>
public static void DrawOrbit(Double inc, Double e, Double sma, Double lan, Double w, Double mEp, Double t, CelestialBody body, Color color, Style style)
{
DrawOrbit(new Orbit(inc, e, sma, lan, w, mEp, t, body), color, style);
}
/// <summary>
/// Draws the orbit.
/// </summary>
/// <param name="orbit">The orbit.</param>
public static void DrawOrbit(Orbit orbit)
{
DrawOrbit(orbit, Color.white, Style.SOLID);
}
/// <summary>
/// Draws the orbit.
/// </summary>
/// <param name="orbit">The orbit.</param>
/// <param name="color">The color of the created line.</param>
public static void DrawOrbit(Orbit orbit, Color color)
{
DrawOrbit(orbit, color, Style.SOLID);
}
/// <summary>
/// Draws the orbit.
/// </summary>
/// <param name="orbit">The orbit.</param>
/// <param name="color">The color of the created line.</param>
/// <param name="style">The style of the created line.</param>
public static void DrawOrbit(Orbit orbit, Color color, Style style)
{
// Only render visible stuff
if (!orbit.referenceBody.scaledBody.GetComponent<Renderer>().isVisible)
return;
// Clear points
points.Clear();
// Calculations for elliptical orbits
if (orbit.eccentricity < 1)
{
for (Int32 i = 0; i < Math.Floor(360.0 / resolution); i++)
points.Add(ScaledSpace.LocalToScaledSpace(orbit.getPositionFromEccAnomaly(i * resolution * Math.PI / 180)));
points.Add(points[0]); // close the loop
}
// Calculations for hyperbolic orbits
else
{
for (Int32 i = -1000; i <= 1000; i += 5)
points.Add(ScaledSpace.LocalToScaledSpace(orbit.getPositionFromEccAnomaly(i * resolution * Math.PI / 180)));
}
// Draw the path
DrawPath(orbit.referenceBody, points, color, style);
}
/// <summary>
/// Draws a path defined by multiple vertices in points.
/// </summary>
/// <param name="points">The vertices of the path.</param>
/// <param name="color">The color of the created path.</param>
/// <param name="style">Whether the path is dashed or solid</param>
public static void DrawPath(CelestialBody body, List<Vector3d> points, Color color, Style style)
{
// Start the GL drawing
GL.PushMatrix();
material.SetPass(0);
GL.LoadPixelMatrix();
GL.Begin(GL.LINES);
GL.Color(color);
// Evaluate the needed amount of steps
Int32 step = (Int32)style;
// Draw every point
for (Int32 i = 0; i < points.Count - 1; i += step)
{
// Occlusion check
Vector3 cameraPos = PlanetariumCamera.Camera.transform.position;
if (Physics.Raycast(cameraPos, (points[i] - cameraPos).normalized) || Physics.Raycast(cameraPos, (points[i + 1] - cameraPos).normalized))
continue;
// Map world coordinates to screen coordinates
screenPoint1 = PlanetariumCamera.Camera.WorldToScreenPoint(points[i]);
screenPoint2 = PlanetariumCamera.Camera.WorldToScreenPoint(points[i + 1]);
// Draw the GL vertices
if (screenPoint1.z > 0 && screenPoint2.z > 0)
{
GL.Vertex3(screenPoint1.x, screenPoint1.y, 0);
GL.Vertex3(screenPoint2.x, screenPoint2.y, 0);
}
}
GL.End();
GL.PopMatrix();
}
/// <summary>
/// Determines whether the specified position is occluded by a celestial body.
/// Borrowed from Sarbian
/// </summary>
/// <param name="worldPosition">The world position.</param>
/// <param name="byBody">The by body.</param>
/// <returns></returns>
public static Boolean IsOccluded(Vector3d worldPosition, CelestialBody byBody)
{
Vector3d camPos = ScaledSpace.ScaledToLocalSpace(PlanetariumCamera.Camera.transform.position);
Vector3d VC = (byBody.position - camPos) / (byBody.Radius - 100);
Vector3d VT = (worldPosition - camPos) / (byBody.Radius - 100);
Double VT_VC = Vector3d.Dot(VT, VC);
// In front of the horizon plane
if (VT_VC < VC.sqrMagnitude - 1) return false;
return VT_VC * VT_VC / VT.sqrMagnitude > VC.sqrMagnitude - 1;
}
}
}
}