gpt4 book ai didi

javascript - HTML5 透视网格

转载 作者:行者123 更新时间:2023-11-28 04:53:48 26 4
gpt4 key购买 nike

我试图在我的 Canvas 上做一个透视网格,并且我已经从另一个网站更改了该功能,结果如下:

    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);
}
}

它创建了几乎良好的透视网格,但它没有缩放高度,因此每个方 block 都有相同的高度。 Here's a working jsFiddle以及它应该是什么样子,就在 Canvas 下方。我想不出任何数学公式来扭曲高度与“透视距离”(顶部)的比例。我希望你明白。抱歉出现语言错误。

任何帮助将不胜感激

问候

最佳答案

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

以下将生成一个可按 X 轴旋转的网格(如您的图片所示),因此我们只需要关注该轴。

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

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

结果将是这样的:

snapshot 3d grid

ONLINE DEMO

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

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

为了调整网格,我们不调整循环(见下文),而是改变fovviewDist以及修改网格 增加或减少细胞数量。

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

enter image description here

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

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 的组合使顶部(在这个 Angular )的线条变得更小。

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

/// 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]);
}

另请注意,位置 0,0 是屏幕中心。这就是为什么我们使用负值从左侧或向上退出。可以看到两条中心线是直线。

这就是全部内容了。要为单元格着色,您只需选择笛卡尔坐标,然后通过调用 rotateX() 进行转换,您将获得 Angular 点所需的坐标。

例如 - 选择一个随机单元格编号(X 轴和 Y 轴上的 -10 到 10 之间):

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();

<强> An animated version 这可以帮助了解发生了什么。

关于javascript - HTML5 透视网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42706965/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com