将圆形碰撞函数转换为 3d 圆柱函数

Turning a circle collision function into a 3d cylinder function

我有一个函数可以 return 线段与圆相交的任何点(最多两个结果,但可能为零):

bool Math::GetLineCircleIntersections(Point theCenter, float theRadius, Point theLineA, Point theLineB, Array<Point>& theResults)
{
    theResults.Reset();
    Point aBA=theLineB-theLineA;
    Point aCA=theCenter-theLineA;

    float aA=aBA.mX*aBA.mX+aBA.mY*aBA.mY;
    float aBBy2=aBA.mX*aCA.mX+aBA.mY*aCA.mY;
    float aC=aCA.mX*aCA.mX+aCA.mY*aCA.mY-theRadius*theRadius;

    float aPBy2=aBBy2/aA;
    float aQ=aC/aA;

    float aDisc=aPBy2*aPBy2-aQ;
    if (aDisc<0) return false;
    float aTmpSqrt=(float)sqrt(aDisc);
    float aABScalingFactor1=-aPBy2+aTmpSqrt;
    float aABScalingFactor2=-aPBy2-aTmpSqrt;

    int aRSpot=0;
    if (aABScalingFactor1<=0.0f && aABScalingFactor1>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor1,theLineA.mY-aBA.mY*aABScalingFactor1);
    if (aDisc==0) return true;
    if (aABScalingFactor2<=0.0f && aABScalingFactor2>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor2,theLineA.mY-aBA.mY*aABScalingFactor2);
    return true;
}

我想将其转换为具有无限圆柱体的 3D 线 - 更复杂的是 3D 圆柱体具有倾斜轴。我知道我真正在做的是与一个以圆柱体中心为中心的球体相交......但是......我该怎么做?我如何选择最佳点使球体居中,然后将线-> 圆交点变成线-> 球体的变化是什么?

(我有一个向量 class 与点 class 完全相同)

(编辑)我确实设法转换为球体函数,却发现呃,不,球体不起作用,因为倾斜的线不会像进入和退出的方式那样进入和退出一个圆柱体。

所以,问题是一样的——在给定圆柱体的原点和轴的情况下,如何将其转换为与无限圆柱体碰撞?

我认为 sphere 不适用于此...

但是,为什么不将 3D 线投影到与圆柱底平行的平面上,从而将其转换为 2D。

所以你得到了 2 个端点 p0,p1 形式的 3D 线和轴 p 上任意点形式的圆柱体,它的半径 r 和轴单位方向向量 d.

  1. 你需要 2 个单位基向量 u,v 来描述圆柱底

    例如,利用叉积和圆柱轴:

    // set u as any unit and non paralel vector to d
    u = (1,0,0)
    if (abs(dot(u,d))>0.75) u=(0,1,0)
    // v set as perpendicular to u,d
    v = cross(d,u)
    // and make u perpendicular to v,d too
    u = cross(v,d)
    
  2. 将问题投影到二维

    p0' = vec2( p0*dot(p0,u) , p0*dot(p0,v) )
    p1' = vec2( p1*dot(p1,u) , p1*dot(p1,v) )
    p'  = vec2( p *dot(p ,u) , p *dot(p ,v) )
    
  3. 解决问题

    现在您只需使用 2D 点 p0',p1',p' 并使用您已有的函数解决您的问题...