Math 两个三维平面之间的精确线性插值
我有两个平面Math 两个三维平面之间的精确线性插值,math,3d,Math,3d,我有两个平面P1和P2指定为法线距离或4D向量。我还有一个参数t。我需要构造一个派生平面P,对于t=0,它与P1重合,对于t=1与P2重合,对于t=(0,1)介于两者之间。最后,P也应表示为4D向量 直观地说,p的构造应确保P1、P2和p在同一条线上相交,并且角度P1和角度;P=(P1∠P2)t 这有一个有效的数学方法吗?这个问题能精确解决吗 澄清 平面之间角度的线性插值实际上是一项要求。换句话说,正常的NP必须通过最短的弧在NP1和NP2之间线性旋转。我不知道计算时间的效率,但它肯
P1
和P2
指定为法线距离或4D向量。我还有一个参数t
。我需要构造一个派生平面P
,对于t=0
,它与P1
重合,对于t=1
与P2
重合,对于t=(0,1)
介于两者之间。最后,P
也应表示为4D向量
直观地说,p
的构造应确保P1
、P2
和p
在同一条线上相交,并且角度P1和角度;P=(P1∠P2)t
这有一个有效的数学方法吗?这个问题能精确解决吗
澄清
平面之间角度的线性插值实际上是一项要求。换句话说,正常的NP必须通过最短的弧在NP1和NP2之间线性旋转。我不知道计算时间的效率,但它肯定可以解决 (想象一个
p\t
(你的p
)就在c\t
旁边a
,a\t
,b
和c\t
是角度。)
在本图中,您需要a_t=a*t,t In(0,1)
我们想在t
方面找到l_t
,重要的是l_t
不仅仅是t*| p|3 |
首先,cos(a)=P1*P2/(| | | | | | | | | | | | P2 | | | | | P2 | | | | | | | | 124
然后a=arccos(P1*P2/(| | | | | | | | | | | | | | P2 | | | |))
另外,b=arccos(P1*P3/(| | | | | | | | | | | | P3 |))
现在,c\u t=pi-(a\u t+b)
,我们可以使用正弦关系来查找l\u t
l|t=sin(a|t)*|P1|/sin(c|t)
最后,p|t=(l|t/| P3 | | | | | | |)P2+((| | P3 | |-l)/| P3 | |)*P1
,它位于P1
和P2
之间的直线上,让a_t
线性依赖于t
,这是一个很好的策略,它利用插值平面法线和两个平面的公共线上的任何点的函数
从每个平面的定义开始,具有法向量n_1=(nx_1,ny_1,nz_1)
,n_2=(nx_2,ny_2,nz_2)
,与原点的距离(沿法线方向测量)为d_1
和d_2
两个平面的公共线沿(非单位)方向e=cross(n_1,n_2)
。这条线上最靠近原点的点由计算给出
point = (d_2*cross(n_1,e)-d_1*cross(n_2,e))/dot(e,e)
符号是用伪代码表示的,其中包含来自大多数常见语言的元素
现在请将其保留在一侧,并将重点放在插值法线上。如果你使用一个函数,它将沿着最小圆弧插值,并且具有相等的间距
vector slerp(vector n_1, vector n_2, float t)
// Assume n_1, n_2 are unit vectors
// Result is always a unit vector
float g = dot(n_1, n_2)
float angle = acos(g)
float f = sin(angle)
return (sin((1-t)*angle)/f)*n_1 + (sin(t*angle)/f)*n_2
end
现在我们可以使用法线n=slerp(n_1,n_2,t)
和距离d=dot(n,point)
定义插值平面,从公共点到新法线的投影
下面的算法扩展了slerp
功能,使其也可用于平面:
plane slerp(plane p_1, plane p_2, float t)
// extract properties from plane
vector n_1 = p_1.normal, n_2 = p_2.normal
float d_1 = p_1.distance, d_2 = p_2.distance
// interpolate
vector e = cross(n_1, n_2))
vector n = slerp(n_1, n_2, t)
vector r = (d_2*cross(n_1,e)-d_1*cross(n_2,e))/dot(e,e)
// construct new plane from normal and distance
return plane(n, dot(r, n))
end
某些帮助程序按预期运行:
float dot(vector a, vector b)
return a.x*b.x + a.y*b.y + a.z*b.z
end
float hypot(vector a)
return sqrt(dot(a,a))
end
vector cross(vector a, vector b)
return vector( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x)
end
vector operator * (float f, vector a)
return vector(f*a.x, f*a.y, f*a.z)
end
vector operator + (vector a, vector b)
return vector(a.x+b.x, a.y+b.y, a.z+b.z)
end
对这些要求进行编码的直接方法是:计算交叉线。然后在那条线上加上旋转,我仍在试图绕着你的答案转。在我看来,这只是部分,解释了旋转向量的基本三角。建造一架符合我标准的飞机需要更多的数学知识。如果我错了,请纠正我。谢谢,我接受你的解决方案。我希望有一些更神奇的东西,比如“把你的平面转换成四元数和宾果游戏”,但是纯三角解就行了。你的代码似乎很简洁。你能详细说明一下要点的公式吗?我知道这一点是两个原始平面和另一个垂直于这两个平面并通过坐标系原点的平面的交点。然而,我不明白这个方程式是如何推导出来的。有参考资料吗?点公式是两个公式的组合。a) 与两个平面相交的线和b)最接近原点的线上的点。“游戏引擎开发的基础”,第1卷-数学,第3章Pucker坐标,第129页,方程式E和G.()