WebGL- 添加标签和拾取对象
WebGL- add label and pick object
我尝试使用颜色索引技术进行拾取,但我想使用光线投射技术并在拾取的 3d 点上添加 3d 标签。
我是 webgl 的新手,我想要一个关于如何使用光线投射在 webgl 中拾取对象的示例代码。
如何在 webgl 中进行投影和取消投影。
我正在使用纯 WebGl 来执行此操作(没有 three.js 或其他框架),请帮助我提供 webgl 代码示例。
如果您对基于 CPU 的解决方案感兴趣,方法如下:
首先将worldspace转换成screenspace坐标,你需要做的就是通过view-projection矩阵变换world 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;
};
将屏幕 space 转换为世界 space 基本上是使用逆视图投影矩阵的逆向操作:
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;
};
然后当你 select 屏幕上的 x,y 坐标时,你可以像这样计算世界 space 中的光线:
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);
}
您必须实施碰撞检测功能,检测光线击中的第一个物体和returns碰撞点(如果需要,还有其他数据)。
有了它,您可以在碰撞点等处创建标签
我尝试使用颜色索引技术进行拾取,但我想使用光线投射技术并在拾取的 3d 点上添加 3d 标签。
我是 webgl 的新手,我想要一个关于如何使用光线投射在 webgl 中拾取对象的示例代码。
如何在 webgl 中进行投影和取消投影。
我正在使用纯 WebGl 来执行此操作(没有 three.js 或其他框架),请帮助我提供 webgl 代码示例。
如果您对基于 CPU 的解决方案感兴趣,方法如下:
首先将worldspace转换成screenspace坐标,你需要做的就是通过view-projection矩阵变换world 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;
};
将屏幕 space 转换为世界 space 基本上是使用逆视图投影矩阵的逆向操作:
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;
};
然后当你 select 屏幕上的 x,y 坐标时,你可以像这样计算世界 space 中的光线:
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);
}
您必须实施碰撞检测功能,检测光线击中的第一个物体和returns碰撞点(如果需要,还有其他数据)。
有了它,您可以在碰撞点等处创建标签