“拼接”多个2d阵列

时间:2016-06-02 14:36:38

标签: javascript arrays algorithm math simplex

编辑(改述问题): 我如何使用提供的smoothstep函数在相邻的2d数组之间创建渐变?每个阵列大小相同,包含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个2d数组,其中包含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);
};

以下页面是我了解这种方法的地方,但我无法理解试图说的是什么。如果有人有时间你能解释我如何在我的情况下实现这一点吗? Link to related question

2 个答案:

答案 0 :(得分:0)

RE:Smoothstep,我在Python的IDLE解释器中快速重新创建了这个函数,这样我就可以将值插入其中并获得即时结果,并且尽可能接近,我所做的就是拉伸你的最小值到0,你的最大值为1,然后相应地规范化值参数。

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

您是否只是尝试使用与Edge A和Edge B相交的50个阵列行/列创建一个实数的数字梯度?

如果是这样,我不知道光滑步是否可行。

无论如何,对于像这样的东西,我会得到一张纸,然后用中间的数组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(正),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,然后在适当的方向上从每个边的起始​​值递增或递减,具体取决于它是否&# 39;是最小值或最大值

如果它比2D数组边缘之间的直线渐变更复杂,我道歉,但可能需要更好地可视化您尝试做的事情。

答案 1 :(得分:0)

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

Smoothstep interpolation

该图显示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之间的值。如果值&lt; min它返回0并且如果值>最大值返回1.如果值介于最小值和最大值之间,则得到插值。

数学上它是一块3 x ^ 2 - 2 x ^ 3的立方体。

我的第一直觉是在每条边上应用Gaussian blurring