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.()