Javascript HTML5透视网格

Javascript HTML5透视网格,javascript,html,math,canvas,Javascript,Html,Math,Canvas,我试图在画布上制作透视网格,我从另一个网站更改了功能,结果如下: function keystoneAndDisplayImage(ctx, img, x, y, pixelHeight, scalingFactor) { var h = img.height, w = img.width, numSlices = Math.abs(pixelHeight), sliceHeight = h / numS

我试图在画布上制作透视网格,我从另一个网站更改了功能,结果如下:

    function keystoneAndDisplayImage(ctx, img, x, y, pixelHeight, scalingFactor) {
    var h = img.height,
            w = img.width,

            numSlices = Math.abs(pixelHeight),

            sliceHeight = h / numSlices,

            polarity = (pixelHeight > 0) ? 1 : -1,
            heightScale = Math.abs(pixelHeight) / h,

            widthScale = (1 - scalingFactor) / numSlices;

    for(var n = 0; n < numSlices; n++) {

        var sy = sliceHeight * n,
                sx = 0,
                sHeight = sliceHeight,
                sWidth = w;

        var dy = y + (sliceHeight * n * heightScale * polarity),
                dx = x + ((w * widthScale * n) / 2),
                dHeight = sliceHeight * heightScale,
                dWidth = w * (1 - (widthScale * n));

        ctx.drawImage(img, sx, sy, sWidth, sHeight,
                dx, dy, dWidth, dHeight);
    }
}
功能密钥和显示图像(ctx、img、x、y、像素高度、缩放因子){
var h=最小高度,
w=最小宽度,
numSlices=Math.abs(像素高度),
切片高度=h/numSlices,
极性=(像素高度>0)?1:-1,
高度比例=数学绝对值(像素高度)/h,
宽度比例=(1-比例因子)/numslice;
对于(var n=0;n
它创建了几乎很好的透视栅格,但它没有缩放高度,因此每个正方形都具有相同的高度。它应该是什么样子,就在画布下面。我想不出任何数学公式能使高度与“透视距离”(顶部)成比例地扭曲。
我希望你能理解。对不起,语言错误 任何帮助都将不胜感激

关于

遗憾的是,除了使用3D方法外,没有合适的方法。但幸运的是,事情并没有那么复杂

下面将生成一个可由X轴旋转的网格(如图所示),因此我们只需聚焦该轴

为了理解发生了什么:我们在笛卡尔坐标空间中定义网格。用一个花哨的词来形容我们将点定义为向量而不是绝对坐标。也就是说,一个网格单元可以从0,0变为1,1,而不是例如10,20变为45,45,只是为了取一些数字

在投影阶段,我们将这些笛卡尔坐标投影到屏幕坐标中

结果如下:

好的,让我们深入探讨一下-首先我们设置一些投影所需的变量,等等:

fov = 512,         /// Field of view kind of the lense, smaller values = spheric
viewDist = 22,     /// view distance, higher values = further away
w = ez.width / 2,  /// center of screen
h = ez.height / 2,
angle = -27,       /// grid angle
i, p1, p2,         /// counter and two points (corners)
grid = 10;         /// grid size in Cartesian
为了调整网格,我们不调整循环(见下文),而是改变
fov
viewDist
以及修改
网格
以增加或减少单元格数量

假设您想要更极端的视图-通过将
fov
设置为128和
viewDist
设置为5,您将使用相同的
网格和
角度获得此结果:

完成所有数学运算的“神奇”函数如下所示:

function rotateX(x, y) {

    var rd, ca, sa, ry, rz, f;

    rd = angle * Math.PI / 180; /// convert angle into radians
    ca = Math.cos(rd);
    sa = Math.sin(rd);

    ry = y * ca;   /// convert y value as we are rotating
    rz = y * sa;   /// only around x. Z will also change

    /// Project the new coords into screen coords
    f = fov / (viewDist + rz);
    x = x * f + w;
    y = ry * f + h;

    return [x, y];
}
就这样。值得一提的是,正是新的Y和Z组合使得顶部的线条更小(在这个角度)

现在我们可以像这样在笛卡尔空间中创建网格,并将这些点直接旋转到屏幕坐标空间中:

/// create vertical lines
for(i = -grid; i <= grid; i++) {
    p1 = rotateX(i, -grid);
    p2 = rotateX(i, grid);
    ez.strokeLine(p1[0], p1[1], p2[0], p2[1]); //from easyCanvasJS, see demo
}

/// create horizontal lines
for(i = -grid; i <= grid; i++) {
    p1 = rotateX(-grid, i);
    p2 = rotateX(grid, i);
    ez.strokeLine(p1[0], p1[1], p2[0], p2[1]);
}

这有助于了解情况。

如果需要透视正确的网格,则需要大量3D数学运算。最重要的构造是。如果您不想构建自己的3D引擎,可以使用现有的引擎,如。看看例子中的源代码,我想在画布中看到的唯一3D东西就是网格。没有严肃的3D数学,有没有办法做到这一点?我只需要添加一些改变每行水平线之间距离的东西(类似的东西)。有什么想法吗?我什么也没发现。使用图像作为背景有什么不对?我正在学习,我想知道如何做全透视网格之类的事情。EasyCanvas非常强大,我看到了文档。还有一个问题:脚本是通过在两侧添加单元格来创建网格的,这就是为什么它在网格中间旋转X。有没有办法以同样的方式旋转,但不是中间旋转,而是以最后一条水平线旋转?“我现在正努力做到这一点。”威兴当然。只需向上“平移”网格,即将单元格从-20添加到0,则0将是轴点,或旋转的基础。如果要在旋转后移动整个网格,只需在rotateX()生成的Y值中添加一个值即可。@Ken AbdiasSoftware是的,我已经自己翻译过了。再次感谢,祝你有一个美好的一天!
c1 = rotateX(cx, cy);         /// upper left corner
c2 = rotateX(cx + 1, cy);     /// upper right corner
c3 = rotateX(cx + 1, cy + 1); /// bottom right corner
c4 = rotateX(cx, cy + 1);     /// bottom left corner

/// draw a polygon between the points
ctx.beginPath();
ctx.moveTo(c1[0], c1[1]);
ctx.lineTo(c2[0], c2[1]);
ctx.lineTo(c3[0], c3[1]);
ctx.lineTo(c4[0], c4[1]);
ctx.closePath();

/// fill the polygon
ctx.fillStyle = 'rgb(200,0,0)';
ctx.fill();