将圆形碰撞函数转换为 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
.
你需要 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)
将问题投影到二维
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) )
解决问题
现在您只需使用 2D 点 p0',p1',p'
并使用您已有的函数解决您的问题...
我有一个函数可以 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
.
你需要 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)
将问题投影到二维
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) )
解决问题
现在您只需使用 2D 点
p0',p1',p'
并使用您已有的函数解决您的问题...