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