Я пытался реализовать щелчок в моем приложении webgl в течение последних 6 часов, и я не могу найти ничего достаточно ясного по этому вопросу.
До сих пор я придумал в псевдокоде:
screenSpace = mousePosition;
normalizedScreenSpace = (screenSpace.x/screen.width, screenSpace.y/screen.height);
camSpace = invertProjectionMatrix * normalizedScreenSpace;
worldSpace = invertViewMatrix * camSpace;
Распечатываем координаты worldSpace, и они не соответствуют другим объектам в сцене. Что я делаю неправильно?
1 ответ
Матрица viewProjection переносит vec3 из мирового пространства в пространство отсечения, и поэтому его инверсия делает обратное, отсекая пространство в мировом пространстве. Чего не хватает, так это разделения перспективы, которое gpu обрабатывает за вас за капотом, поэтому вы также должны это учитывать. Добавьте ширину и высоту экрана, и ваш экран появится в мире:
screenToWorld: function(invViewProjection, screenWidth, screenHeight){
// expects this[2] (z value) to be -1 if want position at zNear and +1 at zFar
var x = 2*this[0]/screenWidth - 1.0;
var y = 1.0 - (2*this[1]/screenHeight); // note: Y axis oriented top -> down in screen space
var z = this[2];
this.setXYZ(x,y,z);
this.applyMat4(invViewProjection);
var m = invViewProjection;
var w = m[3] * x + m[7] * y + m[11] * z + m[15]; // required for perspective divide
if (w !== 0){
var invW = 1.0/w;
this[0] *= invW;
this[1] *= invW;
this[2] *= invW;
}
return this;
},
И обратный расчет:
worldToScreen: function(viewProjectionMatrix, screenWidth, screenHeight){
var m = viewProjectionMatrix;
var w = m[3] * this[0] + m[7] * this[1] + m[11] * this[2] + m[15]; // required for perspective divide
this.applyMat4(viewProjectionMatrix);
if (w!==0){ // do perspective divide and NDC -> screen conversion
var invW = 1.0/w;
this[0] = (this[0]*invW + 1) / 2 * screenWidth;
this[1] = (1-this[1]*invW) / 2 * screenHeight; // screen space Y goes from top to bottom
this[2] *= invW;
}
return this;
},
applyMat4
на vec4. Обратите внимание, что var w = m[3] * x + m[7] * y + m[11] * z + m[15]
должно быть +W*m[15]
, но W неявно предполагается равным 1. Я обновил ответ, чтобы мир отобразил его.
Похожие вопросы
Связанные вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Имейте в виду, что JavaScript — это НЕ то же самое, что Java! Включите все ярлыки, относящиеся к вашему вопросу; например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [svelte] и т. д.