WebGL- добавить метку и выбрать объект
Я пробовал выбирать, используя технику цветового индекса, но я хочу использовать технику лучевого вещания, а также добавить метку 3d на выбранной точке 3d.
Я новичок в webgl, и я хочу пример кода о том, как сделать выбор объекта в webgl с помощью raycasting.
как сделать проект и unproject в webgl.
Я использую чистый WebGl для этого (не Three.js или другие фреймворки), поэтому помогите мне с примерами кода WebGL.
1 ответ
Если вы заинтересованы в решении на базе процессора, вот как:
Прежде всего, чтобы преобразовать мировое пространство в координаты экранного пространства, все, что вам нужно сделать, - это преобразовать мир pos с помощью матрицы проекции вида. Затем вам нужно сделать перспективное деление, разделив x,y,z на w. Это оно. Эта форма имеет наибольшее значение для меня: (Предполагая, что у вас есть соответствующие матричные функции):
vec3.toScreenSpace = function(out, v3, viewProjectionMatrix, width, height){
vec3.transformByMat(out, v3, viewProjectionMatrix);
var m = viewProjectionMatrix;
var w = m[3] * v3[0] + m[7] * v3[1] + m[11] * v3[2] + m[15]; // required for perspective divide
if (w !== 0){
var invW = 1.0/w;
out[0] = (out[0]*invW+1)/2 * width;
out[1] = (1-out[1]*invW)/2 * height; // note: Y axis oriented top -> down in screen space
}
return out;
};
Преобразование экранного пространства в мировое пространство является в основном обратной операцией с матрицей проекции обратного вида:
vec3.toWorldSpace = function(out, v3, viewProjectionMatrix, width, height){
// expects v3[2] (z value) to be -1 if want position at zNear and +1 at zFar
var invViewProj = mat4.inverse(vec3.SHARED_MAT4, viewProjectionMatrix);
var x = 2*v3[0]/width - 1.0;
var y = 1.0 - (2*v3[1]/height); // note: Y axis oriented top -> down in screen space
var z = v3[2];
out[0] = x;
out[1] = y;
out[2] = z;
var m = invViewProj;
vec3.transformByMat(out, out, m);
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;
out[0] *= invW;
out[1] *= invW;
out[2] *= invW;
}
return out;
};
Затем, когда вы выбираете координаты оси и Y на экране, вы можете вычислить луч в мировом пространстве следующим образом:
function screenPickTest(x, y){
var pos = SHARED_V;
var posFar = SHARED_V2;
pos[0] = x;
pos[1] = y;
pos[2] = -1;
posFar[0] = x;
posFar[1] = y;
posFar[2] = +1;
pos = vec3.toWorldSpace(pos, pos, viewProjection, canvas.width, canvas.height);
posFar = vec3.toWorldSpace(posFar, posFar, viewProjection, canvas.width, canvas.height);
var dir = vec3.minus(SHARED_V2, posFar, pos);
return raySweepTestAgainst____(pos, dir, COLLISION_GEOMETRYS);
}
Вы должны реализовать функцию обнаружения столкновений, которая обнаруживает первый объект, куда луч попадает, и возвращает точку столкновения (вместе с другими данными, если требуется).
При этом вы можете создать метку в точке столкновения и т. Д.