Go-GL "Project" метод, дающий неожиданные результаты

Метод Project Go-GL дает мне неожиданно большие координаты экрана.

Подвести итоги:

// Screen is 800x600.
projection := mgl32.Perspective(
    mgl32.DegToRad(45), // Field of view (45 degrees).
    800.0 / 600.0,      // Aspect ratio.
    0.1,                // Near Z at 0.1.
    10)                 // Far Z at 10.
camera := mgl32.LookAtV(
    mgl32.Vec3{0, 0.1, 10}, // Camera out on Z and slightly above.
    mgl32.Vec3{0, 0, 0},    // Looking at the origin.
    mgl32.Vec3{0, 1, 0}     // Up is positive Y.
model := mgl32.Ident4()     // Simple model matrix, to avoid confusion.
modelView := camera.Mul4(model) // The model-view matrix (== camera, here).

// Okay, so what does the origin translate to? Expect center-of-screen, with arbitrary-seeming depth.
origin := mgl32.Vec3{0, 0, 0}
screenOrigin := mgl32.Project(origin, modelView, projection, 0, 0, 800, 600)
fmt.Printf("Origin: (%v, %v, %v)", screenOrigin[0], screenOrigin[1], screenOrigin[2])

// What about the point 5 to the right of the origin?
// Expect increased X, but still less than screenWidth.
// Y and Z should be the same as for the origin.
// In my actual program, I drew (-1,-1,-1)-(1,1,1) cube at (5,0,0) and
// it is completely visible in the window.
test := mgl32.Vec3{5, 0, 0}
screenTest := mgl32.Project(test, modelView, projection, 0, 0, 800, 600)
fmt.Printf("Test:   (%v, %v, %v)", screenTest[0], screenTest[1], screenTest[2])

Результаты, достижения?

Origin: (400, 300, 5.500255)
Test:   (4021.32, 300, 5.500255)

4021,32? Это ПУТЬ с экрана!

Я в значительной степени исключил все переменные, о которых могу думать, кроме рендеринга куба, который я использую в качестве подсказки. Мой код основан на этом, но я переместил камеру и куб: https://github.com/go-gl/examples/tree/master/gl41core-cube

Я получаю те же результаты, если использую (0, 0, 0) в качестве входного вектора и перевожу Ident4() на 5 единиц в +X (что имеет смысл).

Так что я делаю не так? Исходя из положения куба, который я рисую, я ожидал бы что-то вроде X = 625.

1 ответ

Решение

Из любопытства я заглянул в исходный код mgl32. Кажется, что project метод просто неправильный:

obj4 := obj.Vec4(1)

vpp := projection.Mul4(modelview).Mul4x1(obj4)
win[0] = float32(initialX) + (float32(width)*(vpp[0]+1))/2
win[1] = float32(initialY) + (float32(height)*(vpp[1]+1))/2
win[2] = (vpp[2] + 1) / 2

Как можно заметить, перспективное деление отсутствует после умножения матрицы, поэтому функция не будет работать всякий раз, когда w != 1.0f,

В первом примере нельзя заметить ошибку, поскольку x и y равны нулю после умножения матрицы, поэтому деление на w не имеет значения (за исключением z). Во втором примере координата x больше не равна нулю, и ошибка становится видимой.

Другие вопросы по тегам