Skip to content

Commit c178625

Browse files
committed
Fix #66: use direct rendering for navball instead of a camera
1 parent 38a82c9 commit c178625

File tree

1 file changed

+113
-72
lines changed

1 file changed

+113
-72
lines changed

RasterPropMonitor/Handlers/JSIPrimaryFlightDisplay.cs

Lines changed: 113 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ public class JSIPrimaryFlightDisplay : InternalModule
7979

8080
private readonly Quaternion rotateNavBall = Quaternion.Euler(0.0f, 180.0f, 0.0f);
8181

82-
private GameObject cameraBody;
83-
private Camera ballCamera;
84-
8582
private GameObject navBall;
8683
private GameObject overlay;
8784
private GameObject heading;
@@ -90,24 +87,34 @@ public class JSIPrimaryFlightDisplay : InternalModule
9087
private float markerDepth;
9188
private float navballRadius;
9289

90+
struct Marker
91+
{
92+
public GameObject gameObject; // this is intended to mostly be temporary - all we really need here is a matrix
93+
public Mesh mesh;
94+
public Material material;
95+
public bool visible;
96+
}
97+
9398
// Markers...
94-
private GameObject markerPrograde;
95-
private GameObject markerRetrograde;
96-
private GameObject markerManeuver;
97-
private GameObject markerManeuverMinus;
98-
private GameObject markerTarget;
99-
private GameObject markerTargetMinus;
100-
private GameObject markerNormal;
101-
private GameObject markerNormalMinus;
102-
private GameObject markerRadial;
103-
private GameObject markerRadialMinus;
104-
private GameObject markerDockingAlignment;
105-
private GameObject markerNavWaypoint;
99+
private Marker markerPrograde;
100+
private Marker markerRetrograde;
101+
private Marker markerManeuver;
102+
private Marker markerManeuverMinus;
103+
private Marker markerTarget;
104+
private Marker markerTargetMinus;
105+
private Marker markerNormal;
106+
private Marker markerNormalMinus;
107+
private Marker markerRadial;
108+
private Marker markerRadialMinus;
109+
private Marker markerDockingAlignment;
110+
private Marker markerNavWaypoint;
106111

107112
// Misc...
108113
private bool startupComplete;
109114
private bool firstRenderComplete;
110115

116+
float cameraSpan;
117+
111118
private void ConfigureElements(float screenWidth, float screenHeight)
112119
{
113120
// How big is the nav ball, anyway?
@@ -130,11 +137,9 @@ private void ConfigureElements(float screenWidth, float screenHeight)
130137

131138
// Figure out how we have to manipulate the camera to get the
132139
// navball in the right place, and in the right size.
133-
float cameraSpan = navballRadius * screenHeight / navBallDiameter;
140+
cameraSpan = navballRadius * screenHeight / navBallDiameter;
134141
float pixelSize = cameraSpan / (screenHeight * 0.5f);
135142

136-
ballCamera.orthographicSize = cameraSpan;
137-
138143
float newXPos = navBallCenter.x - screenWidth * 0.5f;
139144
float newYPos = screenHeight * 0.5f - navBallCenter.y;
140145
navBallOrigin = navBall.transform.position;
@@ -158,7 +163,6 @@ private void ConfigureElements(float screenWidth, float screenHeight)
158163
overlay.layer = drawingLayer;
159164
overlay.transform.position = new Vector3(0, 0, overlayDepth);
160165
overlay.GetComponent<Renderer>().material = overlayMaterial;
161-
overlay.transform.parent = cameraBody.transform;
162166
}
163167

164168
if (!string.IsNullOrEmpty(headingBar))
@@ -171,7 +175,6 @@ private void ConfigureElements(float screenWidth, float screenHeight)
171175

172176
heading = JUtil.CreateSimplePlane("RPMPFDHeading" + internalProp.propID, new Vector2(headingBarPosition.z * pixelSize, headingBarPosition.w * pixelSize), new Rect(0.0f, 0.0f, 1.0f, 1.0f), drawingLayer);
173177
heading.transform.position = new Vector3(hbXPos * pixelSize, hbYPos * pixelSize, headingAboveOverlay ? (overlayDepth - 0.1f) : (overlayDepth + 0.1f));
174-
heading.transform.parent = cameraBody.transform;
175178
Renderer hdgMatl = null;
176179
heading.GetComponentCached<Renderer>(ref hdgMatl).material = headingMaterial;
177180
hdgMatl.material.SetTextureScale("_MainTex", new Vector2(headingSpan, 1f));
@@ -207,13 +210,10 @@ public bool RenderPFD(RenderTexture screen, float aspect)
207210
{
208211
firstRenderComplete = true;
209212
ConfigureElements((float)screen.width, (float)screen.height);
210-
ballCamera.aspect = aspect;
211213
}
212214

213215
GL.Clear(true, true, backgroundColorValue);
214216

215-
ballCamera.targetTexture = screen;
216-
217217
RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
218218

219219
// Navball is rotated around the Y axis 180 degrees since the
@@ -247,7 +247,10 @@ public bool RenderPFD(RenderTexture screen, float aspect)
247247
MoveMarker(markerRadial, radialPlus, gymbal);
248248
MoveMarker(markerRadialMinus, -radialPlus, gymbal);
249249

250-
JUtil.ShowHide(true, markerNormal, markerNormalMinus, markerRadial, markerRadialMinus);
250+
markerNormal.visible = true;
251+
markerNormalMinus.visible = true;
252+
markerRadial.visible = true;
253+
markerRadialMinus.visible = true;
251254
}
252255
else if (FlightGlobals.speedDisplayMode == FlightGlobals.SpeedDisplayModes.Surface)
253256
{
@@ -268,7 +271,9 @@ public bool RenderPFD(RenderTexture screen, float aspect)
268271
Vector3 burnVector = vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(vessel.orbit).normalized;
269272
MoveMarker(markerManeuver, burnVector, gymbal);
270273
MoveMarker(markerManeuverMinus, -burnVector, gymbal);
271-
JUtil.ShowHide(true, markerManeuver, markerManeuverMinus);
274+
275+
markerManeuver.visible = true;
276+
markerManeuverMinus.visible = true;
272277
}
273278

274279
/*
@@ -324,19 +329,45 @@ public bool RenderPFD(RenderTexture screen, float aspect)
324329
angle = -angle;
325330
}
326331
MoveMarker(markerDockingAlignment, targetOrientationVector, gymbal);
327-
markerDockingAlignment.transform.Rotate(Vector3.up, -angle);
328-
JUtil.ShowHide(true, markerDockingAlignment);
332+
markerDockingAlignment.gameObject.transform.Rotate(Vector3.up, -angle);
333+
markerDockingAlignment.visible = true;
329334
}
330-
JUtil.ShowHide(true, markerTarget, markerTargetMinus);
335+
markerTarget.visible = true;
336+
markerTargetMinus.visible = true;
331337
}
332338

333-
JUtil.ShowHide(true,
334-
cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde);
335-
JUtil.RenderTextureCamera(ballCamera);
336-
JUtil.ShowHide(false,
337-
cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde,
338-
markerManeuver, markerManeuverMinus, markerTarget, markerTargetMinus,
339-
markerNormal, markerNormalMinus, markerRadial, markerRadialMinus, markerDockingAlignment, markerNavWaypoint);
339+
markerPrograde.visible = true;
340+
markerRetrograde.visible = true;
341+
342+
// I wonder if doing this as a command buffer might be more efficient?
343+
344+
GL.PushMatrix();
345+
GL.LoadProjectionMatrix(Matrix4x4.Ortho(-cameraSpan, cameraSpan, -cameraSpan, cameraSpan, 0, navballRadius * 3));
346+
347+
var navballMeshFilter = navBall.GetComponent<MeshFilter>();
348+
var navballRenderer = navBall.GetComponent<MeshRenderer>();
349+
navballRenderer.material.SetPass(0);
350+
Graphics.DrawMeshNow(navballMeshFilter.mesh, navBall.transform.localToWorldMatrix);
351+
352+
DrawMarker(markerPrograde);
353+
DrawMarker(markerRetrograde);
354+
DrawMarker(markerManeuver);
355+
DrawMarker(markerManeuverMinus);
356+
DrawMarker(markerTarget);
357+
DrawMarker(markerTargetMinus);
358+
DrawMarker(markerNormal);
359+
DrawMarker(markerNormalMinus);
360+
DrawMarker(markerRadial);
361+
DrawMarker(markerRadialMinus);
362+
DrawMarker(markerDockingAlignment);
363+
DrawMarker(markerNavWaypoint);
364+
365+
var overlayMesh = overlay.GetComponent<MeshFilter>().mesh;
366+
var overlayMaterial = overlay.GetComponent<MeshRenderer>().material;
367+
overlayMaterial.SetPass(0);
368+
Graphics.DrawMeshNow(overlayMesh, overlay.transform.localToWorldMatrix);
369+
370+
GL.PopMatrix();
340371

341372
return true;
342373
}
@@ -350,15 +381,12 @@ public void ButtonProcessor(int buttonID)
350381
}
351382

352383
private readonly int opacityIndex = Shader.PropertyToID("_Opacity");
353-
private DefaultableDictionary<GameObject, Renderer> markerRenderer = new DefaultableDictionary<GameObject, Renderer>(null);
354-
private void MoveMarker(GameObject marker, Vector3 position, Quaternion voodooGymbal)
384+
385+
private void MoveMarker(Marker marker, Vector3 position, Quaternion voodooGymbal)
355386
{
356387
Vector3 newPosition = ((voodooGymbal * position) * navballRadius) + navBallOrigin;
357-
Renderer r = markerRenderer[marker];
358-
marker.GetComponentCached<Renderer>(ref r);
359-
markerRenderer[marker] = r;
360-
r.material.SetFloat(opacityIndex, Mathf.Clamp01(newPosition.z + 0.5f));
361-
marker.transform.position = new Vector3(newPosition.x, newPosition.y, markerDepth);
388+
marker.material.SetFloat(opacityIndex, Mathf.Clamp01(newPosition.z + 0.5f));
389+
marker.gameObject.transform.position = new Vector3(newPosition.x, newPosition.y, markerDepth);
362390
}
363391

364392
private static Quaternion MirrorX(Quaternion input)
@@ -368,25 +396,43 @@ private static Quaternion MirrorX(Quaternion input)
368396
return new Quaternion(input.x, -input.y, -input.z, input.w);
369397
}
370398

371-
private static GameObject BuildMarker(int iconX, int iconY, float markerSize, Texture gizmoTexture, Color nativeColor, int drawingLayer, int propID, Shader shader)
399+
private static Marker BuildMarker(int iconX, int iconY, float markerSize, Texture gizmoTexture, Color nativeColor, int drawingLayer, int propID, Shader shader)
372400
{
373-
GameObject marker = JUtil.CreateSimplePlane("RPMPFDMarker" + iconX + iconY + propID, markerSize, drawingLayer);
401+
Marker marker = new Marker();
402+
403+
marker.gameObject = JUtil.CreateSimplePlane("RPMPFDMarker" + iconX + iconY + propID, markerSize, drawingLayer);
404+
405+
marker.mesh = marker.gameObject.GetComponent<MeshFilter>().sharedMesh;
374406

375-
Material material = new Material(shader);
376-
material.mainTexture = gizmoTexture;
377-
material.mainTextureScale = Vector2.one / 3f;
378-
material.mainTextureOffset = new Vector2(iconX * (1f / 3f), iconY * (1f / 3f));
379-
material.color = Color.white;
380-
material.SetVector("_Color", nativeColor);
381-
marker.GetComponent<Renderer>().material = material;
407+
marker.material = new Material(shader);
408+
marker.material.mainTexture = gizmoTexture;
409+
marker.material.mainTextureScale = Vector2.one / 3f;
410+
marker.material.mainTextureOffset = new Vector2(iconX * (1f / 3f), iconY * (1f / 3f));
411+
marker.material.color = Color.white;
412+
marker.material.SetVector("_Color", nativeColor);
382413

383-
marker.transform.position = Vector3.zero;
414+
marker.gameObject.transform.position = Vector3.zero;
384415

385-
JUtil.ShowHide(false, marker);
416+
marker.gameObject.SetActive(false);
417+
marker.visible = false;
386418

387419
return marker;
388420
}
389421

422+
private static void DestroyMarker(Marker marker)
423+
{
424+
UnityEngine.Object.Destroy(marker.mesh);
425+
}
426+
427+
private static void DrawMarker(Marker marker)
428+
{
429+
if (marker.visible)
430+
{
431+
marker.material.SetPass(0);
432+
Graphics.DrawMeshNow(marker.mesh, marker.gameObject.transform.localToWorldMatrix);
433+
}
434+
}
435+
390436
public void Start()
391437
{
392438
if (HighLogic.LoadedSceneIsEditor)
@@ -433,24 +479,9 @@ public void Start()
433479
Shader displayShader = JUtil.LoadInternalShader("RPM/DisplayShader");
434480

435481
// Non-moving parts...
436-
cameraBody = new GameObject();
437-
cameraBody.name = "RPMPFD" + cameraBody.GetInstanceID();
438-
cameraBody.layer = drawingLayer;
439482

440483
Vector3 navBallPosition = new Vector3(0.0f, 0.0f, 1.5f);
441484

442-
ballCamera = cameraBody.AddComponent<Camera>();
443-
ballCamera.enabled = false;
444-
ballCamera.orthographic = true;
445-
ballCamera.eventMask = 0;
446-
ballCamera.farClipPlane = 3f;
447-
ballCamera.orthographicSize = 1.0f;
448-
ballCamera.cullingMask = 1 << drawingLayer;
449-
ballCamera.clearFlags = CameraClearFlags.Depth;
450-
ballCamera.transparencySortMode = TransparencySortMode.Orthographic;
451-
ballCamera.transform.position = Vector3.zero;
452-
ballCamera.transform.LookAt(navBallPosition, Vector3.up);
453-
454485
navBall = GameDatabase.Instance.GetModel(navBallModel.EnforceSlashes());
455486
if (navBall == null)
456487
{
@@ -462,7 +493,6 @@ public void Start()
462493
Destroy(navBall.GetComponent<Collider>());
463494
navBall.name = "RPMNB" + navBall.GetInstanceID();
464495
navBall.layer = drawingLayer;
465-
navBall.transform.parent = cameraBody.transform;
466496
navBall.transform.position = navBallPosition;
467497
navBall.GetComponent<Renderer>().material.shader = displayShader;
468498
Texture2D horizonTex = GameDatabase.Instance.GetTexture(horizonTexture.EnforceSlashes(), false);
@@ -494,9 +524,20 @@ public void OnDestroy()
494524
return;
495525
}
496526

497-
JUtil.DisposeOfGameObjects(new GameObject[] { navBall, overlay, heading, markerPrograde, markerRetrograde,
498-
markerManeuver, markerManeuverMinus, markerTarget, markerTargetMinus, markerNormal, markerNormalMinus,
499-
markerRadial, markerRadialMinus, markerDockingAlignment, markerNavWaypoint});
527+
DestroyMarker(markerPrograde);
528+
DestroyMarker(markerRetrograde);
529+
DestroyMarker(markerManeuver);
530+
DestroyMarker(markerManeuverMinus);
531+
DestroyMarker(markerTarget);
532+
DestroyMarker(markerTargetMinus);
533+
DestroyMarker(markerNormal);
534+
DestroyMarker(markerNormalMinus);
535+
DestroyMarker(markerRadial);
536+
DestroyMarker(markerRadialMinus);
537+
DestroyMarker(markerDockingAlignment);
538+
DestroyMarker(markerNavWaypoint);
539+
540+
JUtil.DisposeOfGameObjects(new GameObject[] { navBall, overlay, heading });
500541
}
501542
}
502543
}

0 commit comments

Comments
 (0)