C# 光线/AABB交点不正确

C# 光线/AABB交点不正确,c#,geometry,aabb,C#,Geometry,Aabb,我试图在C中重新实现: 我希望调用testRayC.IntersectionWith(长方体)时返回null,但它返回的是向量(0,12.1,0),它根本不是光线上的点 那么,这是否只是一个添加最终检查的情况,即计算点位于光线上?或者(这就是我所怀疑的),我在转录代码时是否犯了错误?我进行了双重和三重检查,但没有看到任何明显的…代码中的问题是当您执行if(maxDistanceDimension==I){时。原始代码检查if(whichPlane!=I){。我没有您的数据结构,但修复程序应该如

我试图在C中重新实现:

我希望调用
testRayC.IntersectionWith(长方体)
时返回
null
,但它返回的是
向量(0,12.1,0)
,它根本不是光线上的点



那么,这是否只是一个添加最终检查的情况,即计算点位于光线上?或者(这就是我所怀疑的),我在转录代码时是否犯了错误?我进行了双重和三重检查,但没有看到任何明显的…

代码中的问题是当您执行
if(maxDistanceDimension==I){
时。原始代码检查
if(whichPlane!=I){
。我没有您的数据结构,但修复程序应该如下所示:

        for (byte i = 0; i < NUM_DIMENSIONS; ++i)
        {
            if (maxDistanceDimension != i)
            {
                intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i];
                if (intersectionPoint[i] < cuboidMinPoints[i] - MathUtils.FlopsErrorMargin || intersectionPoint[i] > cuboidMaxPoints[i] + MathUtils.FlopsErrorMargin)
                    return null;
            }
            else
            {
                intersectionPoint[i] = candidatePlanes[i];
            }
        }
如果您试图检查命中是否在射线范围内,这可能是一个错误。鉴于您的
方向
似乎没有标准化,
maxDistance
不一定以长度为单位。这在原始算法中可能无关紧要,但如果您要根据某些参数检查
maxDistance
需要规格化
方向的其他长度(使其无量纲),以便

将具有长度单位

顺便说一句,在原文中,我认为以下是错误的:

if(inside)  {
    coord = origin;
    return (TRUE);
}

假设此代码为C而不是C++,则只需设置 COORD 指针,与“代码>原点< /Cuth>指针相同,对调用方没有影响。但是,这个问题不适用于您的版本。

另外,在研究这一点的过程中,我在这里对算法做了一个更字面的c#转录:

public static class RayXCuboid
{
    enum HitQuadrant
    {
        Right = 0,
        Left = 1,
        Middle = 2,
    }

    const int Dimension = 3;

    [Conditional("DEBUG")]
    static void AssertValidArguments<TDoubleList>(params TDoubleList[] args) where TDoubleList : IList<double>
    {
        Debug.Assert(Dimension == 3);
        foreach (var list in args)
            Debug.Assert(list != null && list.Count == Dimension);
    }

    public static bool HitBoundingBox<TDoubleList>(TDoubleList minB, TDoubleList maxB, TDoubleList origin, TDoubleList dir, TDoubleList coord) where TDoubleList : IList<double>
    {
        AssertValidArguments(minB, maxB, origin, dir, coord);

        HitQuadrant[] quadrant = new HitQuadrant[Dimension];
        double[] maxT = new double[Dimension];
        double[] candidatePlane = new double[Dimension];

        /* Find candidate planes; this loop can be avoided if
        rays cast all from the eye(assume perpsective view) */
        bool inside = true;
        for (int i = 0; i < Dimension; i++)
            if (origin[i] < minB[i])
            {
                quadrant[i] = HitQuadrant.Left;
                candidatePlane[i] = minB[i];
                inside = false;
            }
            else if (origin[i] > maxB[i])
            {
                quadrant[i] = HitQuadrant.Right;
                candidatePlane[i] = maxB[i];
                inside = false;
            }
            else
            {
                quadrant[i] = HitQuadrant.Middle;
            }

        /* Ray origin inside bounding box */
        if (inside)
        {
            CopyTo(origin, coord);
            return true;
        }

        /* Calculate T distances to candidate planes */
        for (int i = 0; i < Dimension; i++)
            if (quadrant[i] != HitQuadrant.Middle && dir[i] != 0.0)
                maxT[i] = (candidatePlane[i] - origin[i]) / dir[i];
            else
                maxT[i] = -1.0;

        /* Get largest of the maxT's for final choice of intersection */
        int whichPlane = 0;
        for (int i = 1; i < Dimension; i++)
            if (maxT[whichPlane] < maxT[i])
                whichPlane = i;

        /* Check final candidate actually inside box */
        if (maxT[whichPlane] < 0.0)
        {
            FillWithDefault(coord);
            return false;
        }

        for (int i = 0; i < Dimension; i++)
            if (whichPlane != i)
            {
                coord[i] = origin[i] + maxT[whichPlane] * dir[i];
                if (coord[i] < minB[i] || coord[i] > maxB[i])
                {
                    FillWithDefault(coord);
                    return false;
                }
            }
            else
            {
                coord[i] = candidatePlane[i];
            }
        return true;                /* ray hits box */
    }

    static void FillWithDefault<T>(IList<T> list)
    {
        for (int i = 0; i < list.Count; i++)
            list[i] = default(T);
    }

    static void CopyTo<T>(IList<T> from, IList<T> to)
    {
        int arrayIndex = 0;
        foreach (var item in from)
            to[arrayIndex++] = item;
    }
}
公共静态类光线立方体
{
枚举象限
{
右=0,
左=1,
中间=2,
}
常数int维=3;
[有条件的(“调试”)]
静态无效资产ValidArguments(参数TDoubleList[]args),其中TDoubleList:IList
{
Assert(维度==3);
foreach(参数中的变量列表)
Assert(list!=null&&list.Count==Dimension);
}
公共静态bool HitBoundingBox(TDoubleList minB、TDoubleList maxB、TDoubleList origin、TDoubleList dir、TDoubleList coord),其中TDoubleList:IList
{
资产有效性(minB、maxB、origin、dir、coord);
HitQuadrant[]象限=新HitQuadrant[维度];
double[]最大值=新的双[维度];
double[]candidatePlane=新的双[维度];
/*查找候选平面;如果
光线全部从眼睛投射(假设透视)*/
bool-inside=true;
对于(int i=0;imaxB[i])
{
象限[i]=右象限;
候选平面[i]=maxB[i];
内=假;
}
其他的
{
象限[i]=中间象限;
}
/*边界框内的光线原点*/
如果(内部)
{
CopyTo(原产地、合作伙伴);
返回true;
}
/*计算到候选平面的T距离*/
对于(int i=0;imaxB[i])
{
FillWithDefault(协调);
返回false;
}
}
其他的
{
coord[i]=候选车道[i];
}
返回true;/*光线命中框*/
}
静态void FillWithDefault(IList列表)
{
for(int i=0;i
        if (maxDistance - Length > MathUtils.FlopsErrorMargin)
            return null;
                thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i];
if(inside)  {
    coord = origin;
    return (TRUE);
}
public static class RayXCuboid
{
    enum HitQuadrant
    {
        Right = 0,
        Left = 1,
        Middle = 2,
    }

    const int Dimension = 3;

    [Conditional("DEBUG")]
    static void AssertValidArguments<TDoubleList>(params TDoubleList[] args) where TDoubleList : IList<double>
    {
        Debug.Assert(Dimension == 3);
        foreach (var list in args)
            Debug.Assert(list != null && list.Count == Dimension);
    }

    public static bool HitBoundingBox<TDoubleList>(TDoubleList minB, TDoubleList maxB, TDoubleList origin, TDoubleList dir, TDoubleList coord) where TDoubleList : IList<double>
    {
        AssertValidArguments(minB, maxB, origin, dir, coord);

        HitQuadrant[] quadrant = new HitQuadrant[Dimension];
        double[] maxT = new double[Dimension];
        double[] candidatePlane = new double[Dimension];

        /* Find candidate planes; this loop can be avoided if
        rays cast all from the eye(assume perpsective view) */
        bool inside = true;
        for (int i = 0; i < Dimension; i++)
            if (origin[i] < minB[i])
            {
                quadrant[i] = HitQuadrant.Left;
                candidatePlane[i] = minB[i];
                inside = false;
            }
            else if (origin[i] > maxB[i])
            {
                quadrant[i] = HitQuadrant.Right;
                candidatePlane[i] = maxB[i];
                inside = false;
            }
            else
            {
                quadrant[i] = HitQuadrant.Middle;
            }

        /* Ray origin inside bounding box */
        if (inside)
        {
            CopyTo(origin, coord);
            return true;
        }

        /* Calculate T distances to candidate planes */
        for (int i = 0; i < Dimension; i++)
            if (quadrant[i] != HitQuadrant.Middle && dir[i] != 0.0)
                maxT[i] = (candidatePlane[i] - origin[i]) / dir[i];
            else
                maxT[i] = -1.0;

        /* Get largest of the maxT's for final choice of intersection */
        int whichPlane = 0;
        for (int i = 1; i < Dimension; i++)
            if (maxT[whichPlane] < maxT[i])
                whichPlane = i;

        /* Check final candidate actually inside box */
        if (maxT[whichPlane] < 0.0)
        {
            FillWithDefault(coord);
            return false;
        }

        for (int i = 0; i < Dimension; i++)
            if (whichPlane != i)
            {
                coord[i] = origin[i] + maxT[whichPlane] * dir[i];
                if (coord[i] < minB[i] || coord[i] > maxB[i])
                {
                    FillWithDefault(coord);
                    return false;
                }
            }
            else
            {
                coord[i] = candidatePlane[i];
            }
        return true;                /* ray hits box */
    }

    static void FillWithDefault<T>(IList<T> list)
    {
        for (int i = 0; i < list.Count; i++)
            list[i] = default(T);
    }

    static void CopyTo<T>(IList<T> from, IList<T> to)
    {
        int arrayIndex = 0;
        foreach (var item in from)
            to[arrayIndex++] = item;
    }
}