Мы долгое время пытались найти в канале #python
, как вычислять векторы eye/target/up из матрицы вида с помощью 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)
Но по какой-то причине script работает в течение ~ 20 минут, а sympy пока не может дать какое-либо решение.
Еще одна попытка также попыталась упростить описанную выше общую проблему до более простого, как вы могли бы вычислить вектор вверх?
В более простом контексте определение проблемы будет примерно таким:
-
u,z,x
- это 3D-векторы, которые образуют ортогональный базис . -
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: Thing для извлечения входных данных из матрицы просмотра требуется, чем функция вычисления матрицы, которая является инъективной или биективной, иначе исходная информация будет потеряна. Если вы не добавляете никаких ограничений, вышеуказанные функции определенно не являются инъекционными, потому что в тот момент, когда используется операция нормализации, функция становится автоматически неинъекционной, например:
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
Конечно, это может быть тривиально доказано, просто говоря, что бесконечно векторы могут обеспечить тот же нормализованный вектор.
В этой причине для calculate_view_matrix
было добавлено несколько ограничений. Т.е.: U.norm() - 1
, T.norm() - 1
. Теоретически это должно позволить calculate_view_matrix
стать инъективным... (или нет:))
Итак, главный вопрос заключается в том, как вы можете ограничить/изменить правильно calculate_view_matrix
, чтобы он мог вычислять векторы eye/target/up из матрицы вида?