Html 命中测试伪三维空间

Html 命中测试伪三维空间,html,3d,canvas,Html,3d,Canvas,所以我正在为html5中的canvas元素编写一个小型的伪3d引擎。在下面的代码中,我绘制了一组具有不同位置和旋转(围绕z轴旋转,因此没有变形)的正方形 现在我想知道用户点击哪个方块。在“对象”阵列中,从距离摄影机最远的正方形开始的z位置支持这些项目(以便它们正确绘制)。因此,给定一个相对于画布左上角的3d点,我如何判断单击了哪个正方形 //Draw objects for (var i = 0; i < objects.length; i++) { var object = ob

所以我正在为html5中的canvas元素编写一个小型的伪3d引擎。在下面的代码中,我绘制了一组具有不同位置和旋转(围绕z轴旋转,因此没有变形)的正方形

现在我想知道用户点击哪个方块。在“对象”阵列中,从距离摄影机最远的正方形开始的z位置支持这些项目(以便它们正确绘制)。因此,给定一个相对于画布左上角的3d点,我如何判断单击了哪个正方形

//Draw objects
for (var i = 0; i < objects.length; i++) {
    var object = objects[i];
    var cz = object.position.z - camera.position.z;

    if (cz > 0) {
        cz = 1 / ((cz - 1) * 0.75 + 1);

        context.save();

        context.translate(halfWidth, halfHeight); //viewport transform
        context.scale(1, -1); //invert y axis
        context.scale(cz, cz); //perspective
        context.translate(-camera.position.x, -camera.position.y); //camera transform
        context.translate(object.position.x, object.position.y); //world transform
        context.rotate(object.rotation);

        context.fillStyle = object.color;
        context.fillRect(-40, -40, 80, 80);

        context.restore();
    }
}
//绘制对象
对于(var i=0;i0){
cz=1/((cz-1)*0.75+1);
context.save();
context.translate(半宽半高);//视口变换
context.scale(1,-1);//反转y轴
context.scale(cz,cz);//透视图
context.translate(-camera.position.x,-camera.position.y);//摄像机变换
context.translate(object.position.x,object.position.y);//世界变换
context.rotate(object.rotation);
context.fillStyle=object.color;
fillRect(-40,-40,80,80);
restore();
}
}

另外,如果我在做一些奇怪的事情或是倒退的事情,并且你知道一种改进的方法,我很想听听你的建议

我建议你用相同的变换将对象绘制到一个相同大小的隐藏画布上,但给每个正方形一个唯一的颜色(可能来自索引
I

您可以这样做:

var col = index.toString(16);                 // convert to hex
while (col.length < 6) col = "0"+col;     // pad leading 0s
ctx.fillStyle = "#"+col;
ctx.fillRect(-40,-40,80,80);
var col=index.toString(16);//转换为十六进制
而(列长度<6)col=“0”+col;//焊盘引线0
ctx.fillStyle=“#”+列;
ctx.fillRect(-40,-40,80,80);
然后,当您在可见画布上获得鼠标单击事件时,请查看隐藏画布中的该位置,以获取选定对象的颜色(索引):

var colData = ctx.getImageData(clickX, clickY, 1, 1).data;
var index = (colData[2]<<16) | (colData[1]<<8) | colData[0];
var colData=ctx.getImageData(clickX,clickY,1,1);

var指数=(colData[2]我希望得到更基于数学的解决方案,但这是一个非常有创意的解决方案。这是对复杂场景进行命中测试的一种相当常见的方法。另一种方法是,以编程方式生成canvas对形状所做的变换,在命中点上执行该变换,以创建穿过场景的光线,然后继续如果有任何形状与射线相交(如果有的话,哪一个最接近),请确定。