如何将 3D 坐标转换为 2D (X,Y) 以将文本 div 定位在 3d 游戏对象正下方

How to convert 3D coordinates into 2D (X,Y) for positioning text div just below the 3d game object

我需要在屏幕上将 DIVSet 定位在 3d 播放器正下方的正确 X、Y 位置,但我不确定如何将 x、y、z 转换为 x、y 坐标。

 this.player = player => {
    const pos = interpolate(player.position, player.movementVector)

    resetDivSets()

    calcViewMatrix()
    mat4Translate(viewMatrix, -pos.x * glScale, -3.1 * glScale, pos.y * glScale)
    mat4RotateY(viewMatrix, playerRotation(player, player.drawMovementVector))
    gl.uniformMatrix4fv(uVmatrix, false, viewMatrix)
    gl.uniform3f(uAmbientColor, 1, 1, 1)
    gl.drawElements(gl.TRIANGLES, builtSprites.player.ibCount, gl.UNSIGNED_SHORT, builtSprites.player.ibStart * 2)


// compute a clipspace position

        var clipspace =  WHAT TO HAVE HERE??;

        // divide X and Y by W just like the GPU does.
        clipspace[0] /= clipspace[3];
        clipspace[1] /= clipspace[3];

        // convert from clipspace to pixels
        var pixelX = (clipspace[0] *  0.5 + 0.5) * gl.canvas.width;
        var pixelY = (clipspace[1] * -0.5 + 0.5) * gl.canvas.height;

    addDivSet("Player Name under player object", pixelX , pixelY);

This article covers it

基本上

    // compute a clipspace position
    var modelRelativePosition = [0, 0, 0, 1];  // NOTE!! w = 1
    var clipspace = m4.transformVector(uVmatrix, modelRelativePosition);

    // divide X and Y by W just like the GPU does.
    clipspace[0] /= clipspace[3];
    clipspace[1] /= clipspace[3];

    // convert from clipspace to pixels
    var pixelX = (clipspace[0] *  0.5 + 0.5) * gl.canvas.width;
    var pixelY = (clipspace[1] * -0.5 + 0.5) * gl.canvas.height;

    // position the div
    div.style.left = Math.floor(pixelX) + "px";
    div.style.top  = Math.floor(pixelY) + "px";

其中 transformVector 类似于

  function transformVector(m, v, dst) {
    dst = new Float32Array(4);
    for (var i = 0; i < 4; ++i) {
      dst[i] = 0.0;
      for (var j = 0; j < 4; ++j) {
        dst[i] += v[j] * m[j * 4 + i];
      }
    }
    return dst;
  }

如果您想在 2d 中进行偏移,只需在底部添加即可

    div.style.left = Math.floor(pixelX + offsetX) + "px";
    div.style.top  = Math.floor(pixelY + offsetY) + "px";

const gl = document.createElement('canvas').getContext('webgl');
// use the identity matrix as a test
var uVmatrix = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1,
];

// compute a clipspace position
var modelRelativePosition = [0, 0, 0, 1];  // NOTE! w = 1
var clipspace = transformVector(uVmatrix, modelRelativePosition);

// divide X and Y by W just like the GPU does.
clipspace[0] /= clipspace[3];
clipspace[1] /= clipspace[3];

// convert from clipspace to pixels
var pixelX = (clipspace[0] * 0.5 + 0.5) * gl.canvas.width;
var pixelY = (clipspace[1] * -0.5 + 0.5) * gl.canvas.height;

// position the div
//div.style.left = Math.floor(pixelX) + "px";
//div.style.top = Math.floor(pixelY) + "px";
console.log(Math.floor(pixelX) + "px", Math.floor(pixelY) + "px");

function transformVector(m, v, dst) {
  dst = new Float32Array(4);
  for (var i = 0; i < 4; ++i) {
    dst[i] = 0.0;
    for (var j = 0; j < 4; ++j) {
      dst[i] += v[j] * m[j * 4 + i];
    }
  }
  return dst;
}