2

编辑(改写问题):我将如何使用提供的 smoothstep 函数在相邻二维数组之间创建渐变?每个数组的大小相同,包含范围在 0 和 1 之间的值,通过单纯形噪声从边缘到边缘平滑过渡。结果,我希望相邻数组值之间的差异最大为 0.04

function smoothstep (min, max, value) {
    var x = Math.max(0, Math.min(1, (value-min)/(max-min)));
    return x*x*(3 - 2*x);
};

我有 6 个二维数组,其中包含 0 到 1 之间的值来表示球体表面的高度。要遍历数组的所有值,我有这个:

for (var i = 0; i < cube.faces.length; i++) {
    for (var x = 0; x < cube.faces[i].heightMap.length; x++) {
        for (var z = 0; z < cube.faces[i].heightMap.length; z++) {
            if (x == 0 || x == cube.faces[i].heightMap.length - 1 || z == 0 || z == cube.faces[i].heightMap.length - 1) {
                switch (i) {
                    case 0:
                        if (x == 0) {
                            //match left of face 1 to top of face 4
                        } else if (z == 0) {
                            //match top of face 1 to top of face 6
                        } else if (z == cube.faces[i].heightMap.length - 1) {
                            //match bottom of face 1 to top of face 5
                        } else {
                            //match right of face 1 to top of face 3
                        }
                        break;
                    case 1:
                        if (x == 0) {
                            //match left of face 2 to bottom of face 3
                        } else if (z == 0) {
                            //match top of face 2 to bottom of face 6
                        } else if (z == cube.faces[i].heightMap.length - 1) {
                            //match bottom of face 2 to bottom of face 5
                        } else {
                            //match right of face 2 to bottom of face 4
                        }
                        break;
                    case 2:
                        if (x == 0) {
                            //match left of face 3 to right of face 5
                        } else if (z == 0) {
                            //~~match top of face 3 to right of face 1~~
                        } else if (z == cube.faces[i].heightMap.length - 1) {
                            //~~match bottom of face 3 to left of face 2~~
                        } else {
                            //match right of face 3 to left of face 6
                        }
                        break;
                    case 3:
                        if (x == 0) {
                            //match left of face 4 to right of face 6
                        } else if (z == 0) {
                            //~~match top of face 4 to left of face 1~~
                        } else if (z == cube.faces[i].heightMap.length - 1) {
                            //~~match bottom of face 4 to right of face 2~~
                        } else {
                            //match right of face 4 to left of face 5
                        }
                        break;
                    case 4:
                        break;
                    case 5:
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

但是,我在使面孔匹配时遇到了一些麻烦。调查这个我发现了一个名为“smoothstep”的函数,这似乎正是我所需要的。我不知道如何实现它,我还没有找到对我有用的解释。

function smoothstep(min, max, value) {
    var x = Math.max(0, Math.min(1, (value - min) / (max - min)));
    return x * x * (3 - 2 * x);
};

以下页面是我了解这种方法的地方,但我无法理解要说的内容。如果有人有时间,您能解释一下我如何将其实施到我的情况中吗?链接到相关问题

4

2 回答 2

0

尝试解释smoothstep。您首先从两个值之间的线性插值开始,然后使用三次函数对其进行修改。

平滑步长插值

该图以绿色显示 0 和 1 之间的线性插值,以红色显示平滑版本。我已经将 x 的值限制在范围之外,但您也可以看到黑色立方的延续。

在函数中

function smoothstep(min, max, value) {
    var x = Math.max(0, Math.min(1, (value - min) / (max - min)));
    return x * x * (3 - 2 * x);
};

该函数将始终返回一个介于 0 和 1 之间的值。如果 value < min 它返回 0,如果 value > max 它返回 1。如果 value 在 min 和 max 之间,则得到一个插值。

从数学上讲,它是立方 3 x^2 - 2 x^3 的一部分。


我的第一直觉是沿每个边缘应用高斯模糊。

于 2016-06-10T15:36:08.820 回答
0

RE:Smoothstep,我在 Python 的 IDLE 解释器中快速重新创建了该函数,以便我可以将值插入其中并获得即时结果,据我所知,它所做的只是将您的最小值拉伸到 0,将最大值拉伸到1,然后相应地对值参数进行归一化。

例如,如果您提供的参数(0.2, 0.4, 0.3) 0.3 介于 0.2 和 0.4 之间,那么该函数会将值标准化为大约 0.5

您是否只是想用 50 个与边 A 和边 B 相交的数组行/列创建一个数字的立体渐变?

如果是这样,我不知道smoothstep是否是要走的路。

无论如何,对于这样的事情,我会拿出一张纸,拿出一张纸,画出这样的东西,中间有数组 id 并标记边缘(假设下面的例子中有一个骰子面图案):

        |--A--|
        D  3  B
        |--C--|

        |--A--|
        D  1  B
        |--C--|

|--A--| |--A--| |--A--|
D  2  B D  4  B D  5  B
|--C--| |--C--| |--C--|

        |--A--|
        D  6  B
        |--C--|

然后在你的脑海中将它折叠起来(或将它剪下来并物理折叠立方体)以找到边缘对并绘制箭头指示从边缘向内进入面部的方向。(我喜欢使用 N(orth)、E(ast)、S(outh)、W(est) 来可视化从边缘朝向哪个方向。

航向方向:

N = Same columnID, Start at max RowID and decrement  (going north)
E = Same rowID, Start at min ColumnID and increment  (going east)
S = Same columnID, Start at min RowID and increment  (going south)
W = Same rowID, Start at max ColumnID and decrement  (going west)

你最终会得到一个类似的列表 var list = [1,B,W,, 5,A,S,], [4,B,W,, 5,D,E,]...etc...] (额外的逗号是有意的,代表列表中的空白,接下来填写)

现在,随着该列表的构建,您将从边缘沿您为每个数组记下的任何方向获取值,25 行或列,将其插入空白区域的列表中,您将获得绝对最小值和最大值为您的渐变。例如var list = [[1,B,W,0.3, 5,A,S,0.7],...etc...]

然后,如果它是一个实心渐变,您只需做一些简单的数学运算step_value = Math.abs(list[n][3] - list[n][7])/50 ,然后在适当的方向上从每个边缘的起始值递增或递减,具体取决于它是最小值还是最大值。

如果它比二维数组边缘之间的直线渐变更复杂,我很抱歉,但可能需要更好地可视化您正在尝试做什么。

于 2016-06-08T18:44:28.590 回答