2019년 4월 13일 토요일

# RayCasting - AABB와의 충돌 구현. ( C# 구현 )

# 픽킹 관련으로 구현하다보니 자연스레 레이캐스팅을 만들어보았다. 이것저것 공부할게 덤으로 생겼다. # 해당 소스는 레퍼런스에서 C#으로 바꾸었을뿐이다.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
using UnityEngine;
using System.Collections;

// ref #1 : http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection

public class CustomRayCast : MonoBehaviour
{
    public static bool InterSectWithAABB(Ray ray, CustomAABB aabb)
    {
        if (!aabb.isEnable) return false;

        float tmin = (aabb.minExtent.x - ray.origin.x) / ray.direction.normalized.x;
        float tmax = (aabb.maxExtent.x - ray.origin.x) / ray.direction.normalized.x;

        if (tmin > tmax)
        {
            float tmp = tmin;
            tmin = tmax;
            tmax = tmp;
        }

        float tymin = (aabb.minExtent.y - ray.origin.y) / ray.direction.normalized.y;
        float tymax = (aabb.maxExtent.y - ray.origin.y) / ray.direction.normalized.y;

        if (tymin > tymax)
        {
            float tmp = tymin;
            tymin = tymax;
            tymax = tmp;
        }

        if ((tmin > tymax) || (tymin > tmax))
            return false;

        if (tymin > tmin)
            tmin = tymin;

        if (tymax < tmax)
            tmax = tymax;

        float tzmin = (aabb.minExtent.z - ray.origin.z) / ray.direction.normalized.z;
        float tzmax = (aabb.maxExtent.z - ray.origin.z) / ray.direction.normalized.z;

        if (tzmin > tzmax)
        {
            float tmp = tzmin;
            tzmin = tzmax;
            tzmax = tmp;
        }

        if ((tmin > tzmax) || (tzmin > tmax))
            return false;
        
        if (tzmin > tmin)
            tmin = tzmin;

        if (tzmax < tmax)
            tmax = tzmax;

        return true;
    }

    /// <summary>
    /// 테스트버전.
    /// </summary>
    /// <param name="r"></param>
    /// <param name="aabb"></param>
    /// <returns></returns>
    public static bool InterSectWithAABB_TEST_Version(Ray r, CustomAABB aabb)
    {
        if (!aabb.isEnable) return false;

        Vector3 dirfrac;
        float t;
        // r.direction is unit direction vector of ray
        dirfrac.x = 1.0f / r.direction.x;
        dirfrac.y = 1.0f / r.direction.y;
        dirfrac.z = 1.0f / r.direction.z;
        // aabb.minExtent is the corner of AABB with minimal coordinates - left bottom, aabb.maxExtent is maximal corner
        // r.origin is origin of ray
        float t1 = (aabb.minExtent.x - r.origin.x) * dirfrac.x;
        float t2 = (aabb.maxExtent.x - r.origin.x) * dirfrac.x;
        float t3 = (aabb.minExtent.y - r.origin.y) * dirfrac.y;
        float t4 = (aabb.maxExtent.y - r.origin.y) * dirfrac.y;
        float t5 = (aabb.minExtent.z - r.origin.z) * dirfrac.z;
        float t6 = (aabb.maxExtent.z - r.origin.z) * dirfrac.z;

        float tmin = Mathf.Max(Mathf.Max(Mathf.Min(t1, t2), Mathf.Min(t3, t4)), Mathf.Min(t5, t6));
        float tmax = Mathf.Min(Mathf.Min(Mathf.Max(t1, t2), Mathf.Max(t3, t4)), Mathf.Max(t5, t6));

        // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
        if (tmax < 0)
        {
            t = tmax;
            return false;
        }

        // if tmin > tmax, ray doesn't intersect AABB
        if (tmin > tmax)
        {
            t = tmax;
            return false;
        }

        t = tmin;
        return true;
    }
}

댓글 없음:

댓글 쓰기