我们试图在#python
频道中弄清楚如何使用sympy从视图矩阵中计算眼睛/目标/向上矢量。一种可行的方法可能是:
from sympy import *
from pprint import pprint
v1, v2, v3, v4 = symbols('v1 v2 v3 v4')
v5, v6, v7, v8 = symbols('v5 v6 v7 v8')
v9, v10, v11, v12 = symbols('v9 v10 v11 v12')
v13, v14, v15, v16 = symbols('v13 v14 v15 v16')
V = Matrix([
[v1, v2, v3, v4],
[v5, v6, v7, v8],
[v9, v10, v11, v12],
[v13, v14, v15, v16],
])
u1, u2, u3 = symbols('u1 u2 u3', real=True)
t1, t2, t3 = symbols('t1 t2 t3', real=True)
e1, e2, e3 = symbols('e1 e2 e3', real=True)
U = Matrix([u1, u2, u3])
T = Matrix([t1, t2, t2])
E = Matrix([e1, e2, e3])
def calculate_view_matrix(up, eye, target):
zaxis = (eye - target).normalized()
xaxis = up.cross(zaxis).normalized()
yaxis = zaxis.cross(xaxis)
orientation = Matrix([
[xaxis[0], yaxis[0], zaxis[0], 0],
[xaxis[1], yaxis[1], zaxis[1], 0],
[xaxis[2], yaxis[2], zaxis[2], 0],
[0, 0, 0, 1],
])
translation = Matrix([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[-eye[0], -eye[1], -eye[2], 1],
])
return orientation * translation
print(V - calculate_view_matrix(U, E, T))
s = solve([
V - calculate_view_matrix(U, E, T),
U.norm() - 1,
T.norm() - 1],
[u1, u2, u3, t1, t2, t3, e1, e2, e3])
print(s)
但由于某种原因,脚本已经运行了大约20分钟,而且到目前为止,sympy还没有给出任何解决方案。
另一种尝试也一直试图将上述通用问题简化为更简单的方法,如何计算向上向量?
在更简单的上下文中,问题定义将是这样的:
u,z,x
是3d向量,形成orthonormal basis。z, x
是常量向量u
是未知的向量解决这个问题的等式:
u.cross(z).normalized() - x
如果您试图解决上述通用方程式的简单特殊情况......
from sympy import *
u1,u2,u3=symbols('u1 u2 u3', real = True)
x=Matrix([1,0,0])
z=Matrix([0,0,1])
u=Matrix([u1,u2,u3])
print(solve(u.cross(z).normalized() - x, u))
你得到NotImplementedError: could not solve u2 - Abs(u2)
。
NS:为了从视图矩阵中提取输入,需要比计算矩阵的函数是单射或双射的,否则初始信息将丢失。如果你没有添加任何约束,上面的函数肯定不是内射函数,因为在使用normalize操作的那一刻,函数不再是自动的,例如:
a) normalize(x) = x/|x|
b) To prove normalize is injective then normalize(a)=normalize(b) should give a=b
c) normalize(a)=normalize(b) => a/|a|=b/|b| , which is not true then normalize is not injective
当然,这可以简单地证明只是说infinitelly矢量可以提供相同的标准化矢量。
这就是为什么calculate_view_matrix
增加了一些约束的原因。即:U.norm() - 1
,T.norm() - 1
。理论上,这应该授予calculate_view_matrix
成为单射......(或不是:))
所以主要的问题是,如何正确约束/修改calculate_view_matrix
,以便它可以从视图矩阵中计算出眼睛/目标/向上矢量?
答案 0 :(得分:1)
除了拼写错误(T = Matrix([t1, t2, t2])
)之外,您的Ansatz中还有几个缺陷,即从视图矩阵中恢复,眼睛和目标向量:
v1, v2, ..., v16
中只有6个可以选择(或多或少任意),其他值依赖或确定任何方式(例如v4 = v8 = v12 = 0
,v16 = 1
,{{ 1}},...)。所以一般来说,矩阵差异的方程是矛盾的。v3**2 = 1 - v1**2 - v2**2
,向上矢量U.norm() - 1 = 0
也可以采用无限多个值(一个角度未确定)。要将U
的可能解决方案减少到有限多个案例,可以添加条件U
。U*(E-T) = 0
错误。可以/应该要求T.norm() - 1 = 0
(视图方向)的长度为T - E
。总而言之,我没有办法修复Ansatz s.t.可以使用方程和同情从视图矩阵计算1
。但是U, E, T
可以很容易地从视图矩阵中提取出来:
U, E, T
(满足上述要求)U
可以从最后一行读取-E
在sympy / Python代码中:
E - T