*
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlanoConvexLens : OpticalSurface2D
|
||||
{
|
||||
public float LensRadius = 1.0f;
|
||||
public float CurveRadius = 1.0f;
|
||||
public int SamplesCount = 10;
|
||||
public float Height = 0.1f;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private RaycastMath.RaycastResult2D[] _raycasts;
|
||||
|
||||
public override bool Raycast(Ray2D ray, ref RaycastMath.RaycastResult2D result) {
|
||||
if(_raycasts == null) {
|
||||
_raycasts = new RaycastMath.RaycastResult2D[4];
|
||||
}
|
||||
|
||||
var localSpaceRay = ray;
|
||||
localSpaceRay.origin = transform.InverseTransformPoint(localSpaceRay.origin);
|
||||
localSpaceRay.direction = transform.InverseTransformVector(localSpaceRay.direction).normalized;
|
||||
|
||||
//cs = as + bs
|
||||
//bs = cs - as
|
||||
|
||||
|
||||
float h = Mathf.Sqrt(CurveRadius * CurveRadius - LensRadius * LensRadius);
|
||||
|
||||
|
||||
var sphereCastRay = localSpaceRay;
|
||||
sphereCastRay.origin += Vector2.up * (Mathf.Sign(CurveRadius) * h - Height);
|
||||
|
||||
int raycastsCount = 0;
|
||||
|
||||
bool curveIntersected = RaycastMath.RaycastCircle(sphereCastRay, Mathf.Abs( CurveRadius), ref _raycasts[raycastsCount]);
|
||||
if (curveIntersected) {
|
||||
_raycasts[raycastsCount].Point += Vector2.down * Mathf.Sign(CurveRadius) * (h);
|
||||
|
||||
if(CurveRadius >= 0) {
|
||||
if (_raycasts[raycastsCount].Point.y < 0) {
|
||||
curveIntersected = false;
|
||||
} else {
|
||||
_raycasts[raycastsCount].Point += Vector2.up * Height;
|
||||
raycastsCount++;
|
||||
}
|
||||
} else {
|
||||
if (_raycasts[raycastsCount].Point.y > 0) {
|
||||
curveIntersected = false;
|
||||
} else {
|
||||
_raycasts[raycastsCount].Point += Vector2.up * Height;
|
||||
_raycasts[raycastsCount].Normal = -_raycasts[raycastsCount].Normal;
|
||||
raycastsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vector2 leftHitPoint = Vector2.zero;
|
||||
if(Height > 0.0f && RaycastMath.RayLineSegmentIntersection(localSpaceRay.origin, localSpaceRay.direction, new Vector2(-LensRadius, 0), new Vector2(-LensRadius, Height), ref leftHitPoint)) {
|
||||
_raycasts[raycastsCount].Normal = Vector2.left;
|
||||
_raycasts[raycastsCount].Point = leftHitPoint;
|
||||
raycastsCount++;
|
||||
}
|
||||
|
||||
Vector2 rightHitPoint = Vector2.zero;
|
||||
if(Height > 0.0f && RaycastMath.RayLineSegmentIntersection(localSpaceRay.origin, localSpaceRay.direction, new Vector2(LensRadius, 0), new Vector2(LensRadius, Height), ref rightHitPoint)) {
|
||||
_raycasts[raycastsCount].Normal = Vector2.right;
|
||||
_raycasts[raycastsCount].Point = rightHitPoint;
|
||||
raycastsCount++;
|
||||
}
|
||||
|
||||
Vector2 bottomHitPoint = Vector2.zero;
|
||||
if(LensRadius > 0.0f && RaycastMath.RayLineSegmentIntersection(localSpaceRay.origin, localSpaceRay.direction, new Vector2(-LensRadius, 0), new Vector2(LensRadius, 0), ref bottomHitPoint)) {
|
||||
_raycasts[raycastsCount].Normal = Vector2.down;
|
||||
_raycasts[raycastsCount].Point = bottomHitPoint;
|
||||
raycastsCount++;
|
||||
}
|
||||
|
||||
|
||||
if(raycastsCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = _raycasts.Take(raycastsCount).OrderBy(x => Vector2.Distance(x.Point, localSpaceRay.origin)).First();
|
||||
|
||||
result.Point = transform.TransformPoint(result.Point);
|
||||
result.Normal = transform.InverseTransformVector(result.Normal).normalized;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnValidate() {
|
||||
|
||||
if(CurveRadius > 0 && CurveRadius < LensRadius) {
|
||||
CurveRadius = LensRadius;
|
||||
}
|
||||
|
||||
if (CurveRadius < 0 && CurveRadius > -LensRadius) {
|
||||
CurveRadius = -LensRadius;
|
||||
}
|
||||
|
||||
var points = RadialCurve(LensRadius, CurveRadius, SamplesCount);
|
||||
if(points.Length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Shape = new Line[points.Length - 1 + 3];
|
||||
|
||||
for(int i = 0; i < points.Length - 1; i++) {
|
||||
Shape[i] = new Line() { P1 = points[i] + Vector2.up * Height, P2 = points[i + 1] + Vector2.up * Height };
|
||||
}
|
||||
|
||||
Vector2 p1 = new Vector2(-LensRadius, Height);
|
||||
Vector2 p2 = new Vector2(-LensRadius, 0);
|
||||
Vector2 p3 = new Vector2(LensRadius, 0);
|
||||
Vector2 p4 = new Vector2(LensRadius, Height);
|
||||
|
||||
Shape[Shape.Length - 3] = new Line() { P1 = p1, P2 = p2 };
|
||||
Shape[Shape.Length - 2] = new Line() { P1 = p2, P2 = p3 };
|
||||
Shape[Shape.Length - 1] = new Line() { P1 = p3, P2 = p4 };
|
||||
}
|
||||
|
||||
|
||||
public static Vector2[] RadialCurve(float lenseRadius, float curveRadius, int samplesCount) {
|
||||
|
||||
|
||||
//r*r = x*x + h*h
|
||||
//h*h = r*r - x*x
|
||||
|
||||
Vector2[] result = new Vector2[samplesCount];
|
||||
|
||||
float h = Mathf.Sqrt(curveRadius * curveRadius - lenseRadius * lenseRadius);
|
||||
|
||||
float dx = (-2.0f * lenseRadius) / (samplesCount - 1);
|
||||
|
||||
for (int i = 0; i < samplesCount; i++) {
|
||||
float x2 = lenseRadius + dx * i;
|
||||
float h2 = Mathf.Sqrt(curveRadius * curveRadius - x2 * x2);
|
||||
|
||||
|
||||
result[i] = new Vector2(x2, Mathf.Sign(curveRadius) * (h2 - h));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user