299 lines
10 KiB
C#
299 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AQUAS
|
|
{
|
|
public class AQUAS_ProjectedGrid : MonoBehaviour
|
|
{
|
|
public GameObject waterplane;
|
|
|
|
private GameObject ContainerObj;
|
|
|
|
public Transform[] children;
|
|
|
|
private AQUAS_Caustics[] causticComponents;
|
|
|
|
private Camera cam;
|
|
|
|
private GameObject projectorObj;
|
|
|
|
private Camera projector;
|
|
|
|
private Vector3[] farFrustumCorners;
|
|
|
|
private Vector3[] nearFrustumCorners;
|
|
|
|
private Vector3[] pFarFrustumCorners;
|
|
|
|
private Vector3[] pNearFrustumCorners;
|
|
|
|
private Material[] materials;
|
|
|
|
public float waterLevel;
|
|
|
|
private List<Vector3> intersectionPoints;
|
|
|
|
private Vector4 minMax;
|
|
|
|
private void Start()
|
|
{
|
|
children = new Transform[waterplane.transform.childCount];
|
|
List<AQUAS_Caustics> list = new List<AQUAS_Caustics>();
|
|
for (int i = 0; i < waterplane.transform.childCount; i++)
|
|
{
|
|
children[i] = waterplane.transform.GetChild(i);
|
|
if (waterplane.transform.GetChild(i).GetComponent<AQUAS_Caustics>() != null)
|
|
{
|
|
list.Add(waterplane.transform.GetChild(i).GetComponent<AQUAS_Caustics>());
|
|
}
|
|
}
|
|
Transform[] array = children;
|
|
foreach (Transform transform in array)
|
|
{
|
|
if (transform.name == "Static Boundary")
|
|
{
|
|
transform.parent = null;
|
|
}
|
|
if (transform.GetComponent<AQUAS_Caustics>() != null)
|
|
{
|
|
transform.parent = null;
|
|
}
|
|
}
|
|
causticComponents = list.ToArray();
|
|
cam = GetComponent<Camera>();
|
|
materials = waterplane.GetComponent<SkinnedMeshRenderer>().sharedMaterials;
|
|
nearFrustumCorners = new Vector3[4];
|
|
farFrustumCorners = new Vector3[4];
|
|
pFarFrustumCorners = new Vector3[4];
|
|
pNearFrustumCorners = new Vector3[4];
|
|
waterLevel = waterplane.transform.position.y;
|
|
projectorObj = new GameObject("Projector Object (" + base.transform.name + ")");
|
|
projectorObj.hideFlags = HideFlags.HideAndDontSave;
|
|
projector = projectorObj.AddComponent<Camera>();
|
|
projector.CopyFrom(cam);
|
|
projector.depth = cam.depth - 1f;
|
|
projector.enabled = false;
|
|
intersectionPoints = new List<Vector3>();
|
|
ContainerObj = waterplane.transform.parent.gameObject;
|
|
if (GetComponent<AQUAS_UnderWaterEffect_Simple>() != null)
|
|
{
|
|
GetComponent<AQUAS_UnderWaterEffect_Simple>().waterLevel = waterLevel;
|
|
array = children;
|
|
foreach (Transform transform2 in array)
|
|
{
|
|
if (transform2.name == "Static Boundary" && GetComponent<AQUAS_UnderWaterEffect>() != null)
|
|
{
|
|
GetComponent<AQUAS_UnderWaterEffect>().dynamicBoundary = transform2.gameObject;
|
|
}
|
|
}
|
|
}
|
|
if (!(GetComponent<AQUAS_UnderWaterEffect>() != null))
|
|
{
|
|
return;
|
|
}
|
|
GetComponent<AQUAS_UnderWaterEffect>().waterLevel = waterLevel;
|
|
array = children;
|
|
foreach (Transform transform3 in array)
|
|
{
|
|
if (transform3.name == "Static Boundary")
|
|
{
|
|
GetComponent<AQUAS_UnderWaterEffect>().dynamicBoundary = transform3.gameObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!projectorObj)
|
|
{
|
|
Start();
|
|
}
|
|
Vector3 vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, -1f));
|
|
projector.transform.position = new Vector3(vector.x, Mathf.Max(waterLevel + Mathf.Abs(waterLevel - cam.transform.position.y), waterLevel + 3f), vector.z);
|
|
AQUAS_Caustics[] array = causticComponents;
|
|
foreach (AQUAS_Caustics obj in array)
|
|
{
|
|
obj.waterLevel = waterLevel;
|
|
obj.overrideWaterLevel = true;
|
|
}
|
|
cam.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), cam.farClipPlane, Camera.MonoOrStereoscopicEye.Mono, farFrustumCorners);
|
|
cam.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), cam.nearClipPlane, Camera.MonoOrStereoscopicEye.Mono, nearFrustumCorners);
|
|
projector.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), projector.farClipPlane, Camera.MonoOrStereoscopicEye.Mono, pFarFrustumCorners);
|
|
projector.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), projector.nearClipPlane, Camera.MonoOrStereoscopicEye.Mono, pNearFrustumCorners);
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
farFrustumCorners[j] = base.transform.TransformPoint(farFrustumCorners[j]);
|
|
nearFrustumCorners[j] = base.transform.TransformPoint(nearFrustumCorners[j]);
|
|
pFarFrustumCorners[j] = projectorObj.transform.TransformPoint(pFarFrustumCorners[j]);
|
|
pNearFrustumCorners[j] = projectorObj.transform.TransformPoint(pNearFrustumCorners[j]);
|
|
}
|
|
intersectionPoints.Clear();
|
|
GetAllIntersectionPoints(waterLevel);
|
|
GetAllIntersectionPoints(waterLevel + 1f);
|
|
GetAllIntersectionPoints(waterLevel - 1f);
|
|
projector.aspect = cam.aspect;
|
|
projector.fieldOfView = cam.fieldOfView;
|
|
projector.transform.LookAt(AimProjector());
|
|
}
|
|
|
|
private void OnPreCull()
|
|
{
|
|
Transform[] array = children;
|
|
foreach (Transform transform in array)
|
|
{
|
|
if (!(transform == null))
|
|
{
|
|
if (transform.name == "PrimaryCausticsProjector" || transform.name == "SecondaryCausticsProjector")
|
|
{
|
|
transform.position = new Vector3(base.transform.position.x, waterLevel, base.transform.position.z);
|
|
transform.eulerAngles = new Vector3(90f, 0f, 0f);
|
|
}
|
|
else
|
|
{
|
|
transform.position = new Vector3(base.transform.position.x, waterLevel, base.transform.position.z);
|
|
transform.eulerAngles = new Vector3(0f, 0f, 0f);
|
|
transform.localScale = new Vector3(cam.farClipPlane / 2f, cam.farClipPlane / 2f, cam.farClipPlane / 2f);
|
|
}
|
|
}
|
|
}
|
|
PositionPlane();
|
|
minMax = GetBordersInViewport();
|
|
float num = Vector3.Distance(pNearFrustumCorners[0], pNearFrustumCorners[3]);
|
|
float num2 = Vector3.Distance(pNearFrustumCorners[0], pNearFrustumCorners[1]);
|
|
Material[] array2 = materials;
|
|
foreach (Material material in array2)
|
|
{
|
|
material.SetVector("_ObjectScale", new Vector2(num / projector.nearClipPlane, num2 / projector.nearClipPlane));
|
|
material.SetVector("_RangeVector", minMax);
|
|
material.SetFloat("_waterLevel", waterLevel);
|
|
material.SetFloat("_ProjectGrid", 1f);
|
|
if (material.HasProperty("_PhysicalNormalStrength"))
|
|
{
|
|
material.SetFloat("_PhysicalNormalStrength", 1f);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnPostRender()
|
|
{
|
|
waterplane.transform.parent = ContainerObj.transform;
|
|
}
|
|
|
|
private void PositionPlane()
|
|
{
|
|
waterplane.transform.position = projector.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, projector.nearClipPlane));
|
|
waterplane.transform.eulerAngles = new Vector3(projector.transform.eulerAngles.x - 90f, projector.transform.eulerAngles.y, projector.transform.eulerAngles.z);
|
|
waterplane.transform.parent = projectorObj.transform;
|
|
}
|
|
|
|
private void GetAllIntersectionPoints(float level)
|
|
{
|
|
Vector3 planeOrigin = new Vector3(0f, level, 0f);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
int num = ((i != 3) ? (i + 1) : 0);
|
|
if (LinePlaneIntersection(nearFrustumCorners[i], nearFrustumCorners[num], planeOrigin))
|
|
{
|
|
intersectionPoints.Add(GetIntersectionPoint(nearFrustumCorners[i], nearFrustumCorners[num], planeOrigin));
|
|
}
|
|
if (LinePlaneIntersection(farFrustumCorners[i], farFrustumCorners[num], planeOrigin))
|
|
{
|
|
intersectionPoints.Add(GetIntersectionPoint(farFrustumCorners[i], farFrustumCorners[num], planeOrigin));
|
|
}
|
|
if (LinePlaneIntersection(nearFrustumCorners[i], farFrustumCorners[i], planeOrigin))
|
|
{
|
|
intersectionPoints.Add(GetIntersectionPoint(nearFrustumCorners[i], farFrustumCorners[i], planeOrigin));
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool LinePlaneIntersection(Vector3 startPoint, Vector3 targetPoint, Vector3 planeOrigin)
|
|
{
|
|
Vector3 up = Vector3.up;
|
|
float num = Vector3.Dot(up, startPoint - planeOrigin);
|
|
float num2 = Vector3.Dot(up, targetPoint - planeOrigin);
|
|
if (num * num2 <= 0f)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Vector3 GetIntersectionPoint(Vector3 startPoint, Vector3 targetPoint, Vector3 planeOrigin)
|
|
{
|
|
Vector3 up = Vector3.up;
|
|
float num = Vector3.Dot(up, targetPoint - planeOrigin);
|
|
Vector3 vector = (targetPoint - startPoint) / Vector3.Magnitude(targetPoint - startPoint);
|
|
float num2 = Vector3.Dot(up, vector);
|
|
return targetPoint - vector * (num / num2);
|
|
}
|
|
|
|
private Vector3 AimProjector()
|
|
{
|
|
Vector3 zero = Vector3.zero;
|
|
if (LinePlaneIntersection(cam.transform.position, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f)))
|
|
{
|
|
Vector3 vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
|
|
if (cam.transform.position.y > waterLevel)
|
|
{
|
|
Vector3 startPoint = new Vector3(cam.transform.position.x, Mathf.Max(cam.transform.position.y, waterLevel + 3f), cam.transform.position.z);
|
|
zero = GetIntersectionPoint(startPoint, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f));
|
|
}
|
|
else if (cam.transform.position.y < waterLevel)
|
|
{
|
|
Vector3 startPoint = new Vector3(cam.transform.position.x, Mathf.Min(cam.transform.position.y, waterLevel - 3f), cam.transform.position.z);
|
|
zero = GetIntersectionPoint(startPoint, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f));
|
|
}
|
|
else
|
|
{
|
|
vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
|
|
zero = new Vector3(vector.x, waterLevel, vector.z);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Vector3 vector2 = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
|
|
zero = new Vector3(vector2.x, 0f - Mathf.Abs(vector2.y), vector2.z);
|
|
}
|
|
return zero;
|
|
}
|
|
|
|
private Vector4 GetBordersInViewport()
|
|
{
|
|
float num = 1f;
|
|
float num2 = 0f;
|
|
float num3 = 1f;
|
|
float num4 = 0f;
|
|
for (int i = 0; i < intersectionPoints.Count; i++)
|
|
{
|
|
if (projector.WorldToViewportPoint(intersectionPoints[i]).x < num)
|
|
{
|
|
num = projector.WorldToViewportPoint(intersectionPoints[i]).x;
|
|
}
|
|
}
|
|
for (int j = 0; j < intersectionPoints.Count; j++)
|
|
{
|
|
if (projector.WorldToViewportPoint(intersectionPoints[j]).x > num2)
|
|
{
|
|
num2 = projector.WorldToViewportPoint(intersectionPoints[j]).x;
|
|
}
|
|
}
|
|
for (int k = 0; k < intersectionPoints.Count; k++)
|
|
{
|
|
if (projector.WorldToViewportPoint(intersectionPoints[k]).y < num3)
|
|
{
|
|
num3 = projector.WorldToViewportPoint(intersectionPoints[k]).y;
|
|
}
|
|
}
|
|
for (int l = 0; l < intersectionPoints.Count; l++)
|
|
{
|
|
if (projector.WorldToViewportPoint(intersectionPoints[l]).y > num4)
|
|
{
|
|
num4 = projector.WorldToViewportPoint(intersectionPoints[l]).y;
|
|
}
|
|
}
|
|
return new Vector4((num - 0.5f) * 1.1f, num3 - 0.5f, (num2 - 0.5f) * 1.1f, num4 - 0.5f);
|
|
}
|
|
}
|
|
}
|