Я не думаю, что вы можете избежать небольшой математики, но триггер не так уж и плох:
v = point2 - point1
theta = np.arctan2(v[1], v[0])
phi = np.arctan2(np.linalg.norm(v[:2]), v[2])
tr = pg.Transform3D()
tr.translate(*point1)
tr.rotate(theta * 180 / np.pi, 0, 0, 1)
tr.rotate(phi * 180 / np.pi, 0, 1, 0)
tr.scale(1, 1, np.linalg.norm(v) / 2)
tr.translate(0, 0, 1)
self.m1.setTransform(tr)
И если вы предпочитаете линейную алгебру, а не тригонометрию, это не так уж и сложно. тоже плохо, хотя и более многословно:
# pick 4 points on the untransformed sphere
a = np.array([
[0., 0., -1.],
[0., 0., 1.],
[1., 0., -1.],
[0., 1., -1.],
])
# and 4 corresponding points on the transformed sphere
v1 = np.cross(point1-point2, [0., 0., 1.])
v2 = np.cross(point1-point2, v1)
b = np.array([
point1,
point2,
point1 + v1 / np.linalg.norm(v1),
point1 + v2 / np.linalg.norm(v2),
])
# solve the transform mapping from a to b
tr = pg.solve3DTransform(a, b)
# make this transform work in opengl's homogeneous coordinate system
tr[3,3] = 1
self.m1.setTransform(tr)