我已经看过无数的三维球体交叉问题,不幸的是,它们要么远远超出我的理解能力,要么不能满足我的要求。
这是在Unity游戏引擎中并使用c#
我设法让这段代码正常工作:
public void calculatePoints_H(Vector3 c1p, Vector3 c2p, float c1r, float c2r, out Vector3 startLine, out Vector3 endLine)
{
//c1p = circle one position
//c1r = circle one radius
Vector3 P0 = c1p;
Vector3 P1 = c2p;
float d,a,h;
d = Vector3.Distance(P0,P1);
a = (c1r*c1r - c2r*c2r + d*d)/(2*d);
h = Mathf.Sqrt(c1r*c1r - a*a);
Vector3 P2 = (P1 - P0);
P2 = (P2 * (a/d));
P2 = (P2 + P0);
float x3,y3,x4,y4 = 0;
x3 = P2.x + h*(P1.y - P0.y)/d;
y3 = P2.y - h*(P1.x - P0.x)/d;
x4 = P2.x - h*(P1.y - P0.y)/d;
y4 = P2.y + h*(P1.x - P0.x)/d;;
//draw visual to screen (unity 3D engine)
Debug.DrawLine(new Vector3(x3,0,y3), new Vector3(x4,0,y4),Color.green);
//out parameters for a line renderer
startLine = new Vector3(x3,0,y3);
endLine = new Vector3(x4,0,y4);
}
目前这段代码允许我计算两个球体相交的x和z轴上的两个点,然后绘制一条线。
我想要实现的是xyz交点,所以我也可以在方法中添加高度(y向量3值),这样我就可以从任何方向/高度得到一个与另一个相交的球体
有人可以帮我理解这样做的方法吗,我的脑子有点油炸,我担心这是一个我想念的简单解决方案?
答案 0 :(得分:1)
球体很好,因为你知道交叉点,如果它们是触摸的,那么沿着 AB 的矢量 SphereA 中心到 SphereB 中心。该距离是球半径的函数:
float dA = SphereA.radius / AB.magnitude // % distance along AB starting from SphereA
从那里计算您的交叉点的 AB 的距离:
Vector3 p = SphereA.position + AB * dA; // eq: p`= p + direction * time
示例(使用Unity的内置球体预制):
bool Intersect(out Vector3 ip, float threshold=0.1f){
// vector from sphere 1 -> sphere 2
Vector3 ab = Sphere2.transform.position - Sphere1.transform.position;
// Calculate radius from Unity built-in sphere.
// Unity spheres are unit spheres (diameter = 1)
// So diameter = scale, thus radius = scale / 2.0f.
// **Presumes uniform scaling.
float r1 = Sphere1.transform.localScale.x / 2.0f;
float r2 = Sphere2.transform.localScale.x / 2.0f;
// When spheres are too close or too far apart, ignore intersection.
float diff = Mathf.Abs(r2 + r1 - ab.magnitude);
if( diff >= threshold) {
ip = Vector3.zero;
return false;
}
// Intersection is the distance along the vector between
// the 2 spheres as a function of the sphere's radius.
ip = Sphere1.transform.position + ab * r1/ab.magnitude;
return true;
}
示例用法:
void FixedUpdate(){
Vector3 p; //will hold intersection point if one is found
if(Intersect(out p,0.1f)){
IntersectionPoint.transform.position = p;
IntersectionPoint.renderer.enabled = true;
} else {
IntersectionPoint.renderer.enabled = false;
}
}
这只会返回一个交叉点。多个交叉点,如球体重叠时,是一个不同的问题需要解决。