【问题标题】:Turning a circle collision function into a 3d cylinder function将圆形碰撞函数转换为 3d 圆柱函数
【发布时间】:2021-09-24 23:12:52
【问题描述】:

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

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 圆柱具有倾斜轴的复杂性。我知道我真正在做的是与一个球体相交,该球体以圆柱体中心为中心,直线平面将其切割......但是......我该怎么做?如何选择使球体居中的最佳点,然后这样做,我将线->圆交叉点变为线->球体的变化是什么?

(我有一个和点类一模一样的向量类)

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

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

【问题讨论】:

    标签: geometry line collision intersection


    【解决方案1】:

    我不认为 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' 并使用已有的功能解决您的问题...

    【讨论】:

    • 嗨,Spektre,这似乎是一个很好的解决方案——但是!在我得到我的 2d 点后,我如何反转该计算以将它们放回对象空间?我已经习惯了用矩阵做这些事情,只是反转来撤消它......
    • 没关系,设法弄清楚了!感谢您的解决方案!
    • @KiraHoneybee 还有更多方法...例如让q' 成为二维解决方案,因此:t = dot(q'-p0',p1'-p0')/|p1'-p0'|; q = p0 + t*(p1-p0);
    猜你喜欢
    • 1970-01-01
    • 2014-03-23
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多