Integrated Sebastian Lague's Planet Generator Created Tour function in SectorRenderer which makes the camera follow each terrestrial planet in turn
113 lines
No EOL
4 KiB
C#
113 lines
No EOL
4 KiB
C#
using UnityEngine;
|
|
|
|
public static class CameraUtility {
|
|
static readonly Vector3[] cubeCornerOffsets = {
|
|
new Vector3 (1, 1, 1),
|
|
new Vector3 (-1, 1, 1),
|
|
new Vector3 (-1, -1, 1),
|
|
new Vector3 (-1, -1, -1),
|
|
new Vector3 (-1, 1, -1),
|
|
new Vector3 (1, -1, -1),
|
|
new Vector3 (1, 1, -1),
|
|
new Vector3 (1, -1, 1),
|
|
};
|
|
|
|
// http://wiki.unity3d.com/index.php/IsVisibleFrom
|
|
public static bool VisibleFromCamera (Renderer renderer, Camera camera) {
|
|
Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes (camera);
|
|
return GeometryUtility.TestPlanesAABB (frustumPlanes, renderer.bounds);
|
|
}
|
|
|
|
public static bool BoundsOverlap (MeshFilter nearObject, MeshFilter farObject, Camera camera) {
|
|
|
|
var near = GetScreenRectFromBounds (nearObject, camera);
|
|
var far = GetScreenRectFromBounds (farObject, camera);
|
|
|
|
// ensure far object is indeed further away than near object
|
|
if (far.zMax > near.zMin) {
|
|
// Doesn't overlap on x axis
|
|
if (far.xMax < near.xMin || far.xMin > near.xMax) {
|
|
return false;
|
|
}
|
|
// Doesn't overlap on y axis
|
|
if (far.yMax < near.yMin || far.yMin > near.yMax) {
|
|
return false;
|
|
}
|
|
// Overlaps
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static float GetScreenHeight (Vector3 a, Vector3 b, Camera camera) {
|
|
Debug.DrawLine(a,b,Color.red);
|
|
Vector3 viewA = camera.WorldToViewportPoint (a);
|
|
Vector3 viewB = camera.WorldToViewportPoint (b);
|
|
float dst = Mathf.Abs (viewA.y - viewB.y);
|
|
Debug.Log ("A: " + viewA.y + " B: " + viewB.y + " " + dst);
|
|
return dst;
|
|
}
|
|
|
|
// With thanks to http://www.turiyaware.com/a-solution-to-unitys-camera-worldtoscreenpoint-causing-ui-elements-to-display-when-object-is-behind-the-camera/
|
|
public static MinMax3D GetScreenRectFromBounds (MeshFilter meshFilter, Camera camera) {
|
|
MinMax3D minMax = new MinMax3D (float.MaxValue, float.MinValue);
|
|
|
|
Vector3[] screenBoundsExtents = new Vector3[8];
|
|
var localBounds = meshFilter.sharedMesh.bounds;
|
|
bool anyPointIsInFrontOfCamera = false;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
Vector3 localSpaceCorner = localBounds.center + Vector3.Scale (localBounds.extents, cubeCornerOffsets[i]);
|
|
Vector3 worldSpaceCorner = meshFilter.transform.TransformPoint (localSpaceCorner);
|
|
Vector3 viewportSpaceCorner = camera.WorldToViewportPoint (worldSpaceCorner);
|
|
|
|
if (viewportSpaceCorner.z > 0) {
|
|
anyPointIsInFrontOfCamera = true;
|
|
} else {
|
|
// If point is behind camera, it gets flipped to the opposite side
|
|
// So clamp to opposite edge to correct for this
|
|
viewportSpaceCorner.x = (viewportSpaceCorner.x <= 0.5f) ? 1 : 0;
|
|
viewportSpaceCorner.y = (viewportSpaceCorner.y <= 0.5f) ? 1 : 0;
|
|
}
|
|
|
|
// Update bounds with new corner point
|
|
minMax.AddPoint (viewportSpaceCorner);
|
|
}
|
|
|
|
// All points are behind camera so just return empty bounds
|
|
if (!anyPointIsInFrontOfCamera) {
|
|
return new MinMax3D ();
|
|
}
|
|
|
|
return minMax;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public struct MinMax3D {
|
|
public float xMin;
|
|
public float xMax;
|
|
public float yMin;
|
|
public float yMax;
|
|
public float zMin;
|
|
public float zMax;
|
|
|
|
public MinMax3D (float min, float max) {
|
|
this.xMin = min;
|
|
this.xMax = max;
|
|
this.yMin = min;
|
|
this.yMax = max;
|
|
this.zMin = min;
|
|
this.zMax = max;
|
|
}
|
|
|
|
public void AddPoint (Vector3 point) {
|
|
xMin = Mathf.Min (xMin, point.x);
|
|
xMax = Mathf.Max (xMax, point.x);
|
|
yMin = Mathf.Min (yMin, point.y);
|
|
yMax = Mathf.Max (yMax, point.y);
|
|
zMin = Mathf.Min (zMin, point.z);
|
|
zMax = Mathf.Max (zMax, point.z);
|
|
}
|
|
}
|
|
|
|
} |