javascript - 如何在模型 View 转换后获取正在绘制的对象的二维尺寸以在 webgl 上进行 HitTest

标签 javascript html css node.js webgl

我遵循 webgl 基础知识并绘制 2d 对象并使用矩阵缩放顶点和渲染。

在渲染之前,我传递设置为顶点的 width/height 来渲染四边形。这定义了对象的大小。但是在顶点着色器中,我像这样对这些顶点应用变换:

in vec2 aPosition;
in vec2 aTexCoord;

out vec2 vQuadCoord;

uniform mat3 uMatrix;

void main() {

  vec2 position = (uMatrix * vec3(aPosition, 1)).xy;

  vQuadCoord = aTexCoord;

  gl_Position = vec4(position, 0, 1);

}

此矩阵控制对象的平移/旋转/缩放。渲染后,我想知道这个对象的边界。但特别是在缩放之后我不知道界限。如果我在 x,y 处平移这个对象(带有矩阵),它的位置是已知的,但是如果我缩放这个对象,x 会向左移动,移动量未知。 webgl 基础知识没有提到这个主题,什么是检测对象边界和精确转换的好方法,因为我也有枢轴问题,我可能会问另一个问题。

最佳答案

您需要将鼠标坐标转换为裁剪空间,然后将它们乘以矩阵的逆矩阵。这将为您提供相对于 aPosition 值的鼠标坐标。

之后就看你的了。如果提供给 aPosition 的值(顶点)是一个矩形,那么您可以只检查该矩形的变换点。如果它们是更复杂的形状,如星形,那么您需要制作自己的函数来执行 point in starpoint in triangle 并检查每个三 Angular 形,但至少转换后,鼠标位置位于相对于您的顶点的坐标中。您还可以在初始时间计算顶点的边界框,并使用它来测试变换后的点。

function main() {
  const gl = document.querySelector('canvas').getContext('webgl2');
  if (!gl) {
    return alert('need WebGL2');
  }
  
  const vs = `#version 300 es
in vec2 aPosition;

uniform mat3 uMatrix;

void main() {

  vec2 position = (uMatrix * vec3(aPosition, 1)).xy;

  gl_Position = vec4(position, 0, 1);

}
  `;
  const fs = `#version 300 es
  precision mediump float;
  uniform vec4 color;
  out vec4 outColor;
  void main() {
    outColor = color;
  }

  `;
  
  const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
  
  // create a quad that starts at 0,0 and is 20 units wide and 10 tall
  const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
    aPosition: {
      numComponents: 2,
      data: [
        0, 0,
        0, 10,
        20, 0,
        
        20, 0,
        0, 10,
        20, 10,
      ],
    }
  });
  const vao = twgl.createVAOFromBufferInfo(gl, programInfo, bufferInfo);
  
  let mouseClipX = 0;
  let mouseClipY = 0;
  const infoElem = document.querySelector('#info');
  
  function render(time) {
    t = time / 1000;
    
    twgl.resizeCanvasToDisplaySize(gl.canvas);
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    
    gl.useProgram(programInfo.program);
    gl.bindVertexArray(vao);
    
    let mat = m3.projection(gl.canvas.width, gl.canvas.height);
    
    mat = m3.translate(
       mat, 
       150 + Math.sin(t * 0.1) * 100,
       75 + Math.cos(t * 0.2) * 50);
    mat = m3.rotate(mat, t * 0.3);
    mat = m3.scale(
       mat, 
       2 + Math.sin(t * 0.4) * 0.5,
       2 + Math.cos(t * 0.5) * 0.5);
       
       
    // convert clipspace mouse to aPosition relative values
    // 'mat' takes aPosition and converts to clip space
    // so the inverse of 'mat' would take clip space and
    // convert back to aPosition space.
    const invMat = m3.inverse(mat);
    const p = m3.transformPoint(invMat, [mouseClipX, mouseClipY]);
    
    // now check in aPosition space. It's a 20x10 rect starting at 0,0 so
    const inbox = p[0] >= 0 && p[0] < 20 &&
                  p[1] >= 0 && p[1] < 10;
       
    
    twgl.setUniforms(programInfo, {
      uMatrix: mat,
      color: inbox ? [1, 0, 0, 1] : [0, 0, 1, 1],
    });
    twgl.drawBufferInfo(gl, bufferInfo);
        
    infoElem.textContent = inbox ? 'mouse in rect' : 'no hit';
    
    requestAnimationFrame(render);    
  }
  requestAnimationFrame(render);
  
  gl.canvas.addEventListener('mousemove', (event) => {
    // convert canvas relative mouse coordinates to clip space
    mouseClipX = (event.offsetX / gl.canvas.clientWidth ) *  2 - 1;
    mouseClipY = (event.offsetY / gl.canvas.clientHeight) * -2 + 1;  // note we flip Y
  });
}


main();
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/m3.js"></script>
<canvas></canvas>
<pre id="info"></pre>

关于javascript - 如何在模型 View 转换后获取正在绘制的对象的二维尺寸以在 webgl 上进行 HitTest ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57697719/

相关文章:

javascript - 使用 Javascript 替换文本而不丢失内部标签

javascript - 读取JSON文件,更新值并保存修改

javascript - Marionette 中布局内的布局

javascript - 在 Vue 应用程序中导入脚本后 undefined variable

javascript - 移动包含 youtube 视频的 iframe onresize

javascript - 如果滚动更改背景图像

html - 在 Firefox 中居中图例

javascript - 使用带有 HTML 自定义元素的模板

html - 以不同速度同时进行多个 CSS3 变换转换

css - 我无法让我的网站居中