Advanced POC - portals, dialogue system + floating words, room loading
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility functions for portal camera rendering and visibility calculations.
|
||||
/// Used to optimize portal rendering by detecting visibility and overlaps.
|
||||
/// </summary>
|
||||
public static class PortalCameraUtility
|
||||
{
|
||||
private 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),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Tests if a renderer is visible from the camera's perspective.
|
||||
/// Uses frustum culling to determine visibility.
|
||||
/// </summary>
|
||||
public static bool VisibleFromCamera(Renderer renderer, Camera camera)
|
||||
{
|
||||
Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return GeometryUtility.TestPlanesAABB(frustumPlanes, renderer.bounds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if two objects' screen-space bounding boxes overlap when viewed from a camera.
|
||||
/// Used to determine if one portal is being viewed through another portal (recursion).
|
||||
/// Returns true if the far object is visible through/behind the near object.
|
||||
/// </summary>
|
||||
public static bool BoundsOverlap(MeshFilter nearObject, MeshFilter farObject, Camera camera)
|
||||
{
|
||||
var near = GetScreenRectFromBounds(nearObject, camera);
|
||||
var far = GetScreenRectFromBounds(farObject, camera);
|
||||
|
||||
if (far.zMax > near.zMin)
|
||||
{
|
||||
if (far.xMax < near.xMin || far.xMin > near.xMax)
|
||||
return false;
|
||||
|
||||
if (far.yMax < near.yMin || far.yMin > near.yMax)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a mesh's 3D bounding box to screen-space coordinates (viewport space).
|
||||
/// Handles corner cases where parts of the mesh are behind the camera.
|
||||
/// Returns a MinMax3D struct containing the min/max viewport coordinates (x, y) and depth (z).
|
||||
/// </summary>
|
||||
public static MinMax3D GetScreenRectFromBounds(MeshFilter renderer, Camera mainCamera)
|
||||
{
|
||||
MinMax3D minMax = new MinMax3D(float.MaxValue, float.MinValue);
|
||||
var localBounds = renderer.sharedMesh.bounds;
|
||||
bool anyPointIsInFrontOfCamera = false;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
Vector3 localSpaceCorner = localBounds.center + Vector3.Scale(localBounds.extents, _cubeCornerOffsets[i]);
|
||||
Vector3 worldSpaceCorner = renderer.transform.TransformPoint(localSpaceCorner);
|
||||
Vector3 viewportSpaceCorner = mainCamera.WorldToViewportPoint(worldSpaceCorner);
|
||||
|
||||
if (viewportSpaceCorner.z > 0)
|
||||
{
|
||||
anyPointIsInFrontOfCamera = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewportSpaceCorner.x = (viewportSpaceCorner.x <= 0.5f) ? 1 : 0;
|
||||
viewportSpaceCorner.y = (viewportSpaceCorner.y <= 0.5f) ? 1 : 0;
|
||||
}
|
||||
|
||||
minMax.AddPoint(viewportSpaceCorner);
|
||||
}
|
||||
|
||||
if (!anyPointIsInFrontOfCamera)
|
||||
{
|
||||
return new MinMax3D();
|
||||
}
|
||||
|
||||
return minMax;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 3D axis-aligned bounding box in viewport/screen space.
|
||||
/// X and Y are in viewport coordinates [0,1], Z is depth from camera.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d0beb143dec2a948b0c8348fc80e02b
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.Gameplay.Portals
|
||||
{
|
||||
/// <summary>
|
||||
/// Shared constants for the portal system.
|
||||
/// Contains only hardcoded values used in multiple places (shader properties, object names, thresholds).
|
||||
/// Does NOT include default values for serialized fields (those are configured per-instance in Inspector).
|
||||
/// </summary>
|
||||
public static class PortalConstants
|
||||
{
|
||||
public const string PORTAL_CAMERA_NAME = "PortalCamera";
|
||||
|
||||
public const string SHADER_PROPERTY_MAIN_TEXTURE = "_MainTex";
|
||||
public const string SHADER_PROPERTY_DISPLAY_MASK = "_DisplayMask";
|
||||
public const string SHADER_PROPERTY_SLICE_NORMAL = "_sliceNormal";
|
||||
public const string SHADER_PROPERTY_SLICE_OFFSET = "_sliceOffsetDst";
|
||||
public const string SHADER_PROPERTY_SLICE_CENTER = "_SliceCenter";
|
||||
|
||||
public const float MIN_VOLUME_THRESHOLD = 0.001f;
|
||||
public const float GAMEPAD_DEADZONE = 0.01f;
|
||||
|
||||
public const int RENDER_TEXTURE_DEPTH = 24;
|
||||
public const RenderTextureFormat RENDER_TEXTURE_FORMAT = RenderTextureFormat.ARGB32;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37282c5300e816f498b180139042682b
|
||||
Reference in New Issue
Block a user