UnityでRayとMeshの交点の取得を実装する ～裏面でも取得して欲しい～

# 「Moller-Trumbore」アルゴリズムです
# コード説明
Unityでメッシュの内部からのRayで、交点を取得する必要があったので自前で実装しました。上の方の関数がメッシュフィルターとの判定で、下が一つの三角形との判定です。引数seeFront,seeBackを変更することで、用途に応じて使い分けられます。

# 参考文献
これらを読んだらコードの中身が理解できます。複雑な計算の実装に関しては(あー大学の授業でやったわこんなん)みたいな感じで、参考文献のものをコピペしました。これを読んでるあなたも、私のコードをコピペするか、wikiのをコピペするといいと思います。
https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
https://shikousakugo.wordpress.com/2012/05/29/ray-intersection/
https://shikousakugo.wordpress.com/2012/06/27/ray-intersection-2/
https://shikousakugo.wordpress.com/2012/07/01/ray-intersection-3/
# コード
```
using UnityEngine;

//https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
//https://shikousakugo.wordpress.com/2012/05/29/ray-intersection/
//https://shikousakugo.wordpress.com/2012/06/27/ray-intersection-2/
//https://shikousakugo.wordpress.com/2012/07/01/ray-intersection-3/
public static class MollerTrumboreRayChack
{
    public static bool GetRayIntersectMesh(Vector3 rayOrigin, Vector3 rayVector,MeshFilter mf, out Vector3 Intersect, bool seeFront = true, bool seeBack = true)
    { 
        Intersect = Vector3.zero;
        Mesh mesh = mf.mesh;
        int[] triangles = mesh.triangles;
        Vector3[] vertices=mesh.vertices;

        Vector3[] verticesWorldPos=new Vector3[vertices.Length];
        Matrix4x4 localToWorld = mf.transform.localToWorldMatrix;
        for(int i = 0; i < vertices.Length; i++)
        {
            verticesWorldPos[i]= localToWorld.MultiplyPoint3x4(vertices[i]);
        }
        for (int i = 0; i < triangles.Length; i+=3)
        {
            if (RayIntersectsTriangle(rayOrigin, rayVector, verticesWorldPos[triangles[i]], verticesWorldPos[triangles[i+1]], verticesWorldPos[triangles[i+2]], out Vector3 thisout,seeFront,seeBack))
            {
                Intersect=thisout;
                return true;
            }
        }
        return false;
    }
    public static bool RayIntersectsTriangle(Vector3 rayOrigin,Vector3 rayVector,Vector3 vertex0, Vector3 vertex1, Vector3 vertex2, out Vector3 outIntersectionPoint,bool seeFront=true ,bool seeBack=true)
    {
        outIntersectionPoint = new Vector3();

        const float EPSILON = 0.000001f;
        Vector3 edge1, edge2, h, s, q;
        float a, f, u, v;
        edge1 = vertex1 - vertex0;
        edge2 = vertex2 - vertex0;
        h = Vector3.Cross(rayVector,edge2);
        a = Vector3.Dot(edge1,h);
        if (-EPSILON < a && a < EPSILON) return false;//aがに近いとき、平行なので偽
        if (a < -EPSILON && !seeBack) return false;//aが0以下の時、判定する面はRayに対して裏面を向いているので、裏面を判定しないならば偽
        if (EPSILON < a && !seeFront) return false;//aが0以上の時、判定する面はRayに対して表面を向いているので、表面を判定しないならば偽
        f = 1.0f / a;
        s = rayOrigin - vertex0;
        u = f * Vector3.Dot(s,h);

        if (u < 0.0f || u > 1.0f) return false;

        q = Vector3.Cross(s,edge1);
        v = f * Vector3.Dot(rayVector,q);

        if (v < 0.0f || u + v > 1.0f)
            return false;

        // At this stage we can compute t to find out where the intersection point is on the line.
        float t = f * Vector3.Dot(edge2,q);

        if (t > EPSILON) // ray intersection
        {
            outIntersectionPoint = rayOrigin + rayVector * t;
            return true;
        }
        else // This means that there is a line intersection but not a ray intersection.
            return false;
    }
}

```