"Сшивание" нескольких 2d массивов
РЕДАКТИРОВАТЬ (перефразированный вопрос): Как бы я использовал предоставленную функцию сглаживания для создания постепенного перехода между смежными 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);
};
На следующей странице я узнал об этом методе, но не могу понять, что пытается сказать. если у кого есть время, не могли бы вы объяснить, как я могу реализовать это в моей ситуации? Ссылка на связанный вопрос
2 ответа
RE: Плавный шаг, я воссоздал функцию в интерпретаторе IDLE Python очень быстро, чтобы я мог вставить в нее значения и получить мгновенные результаты, и, насколько я могу судить, все, что он делает, это растягивает ваше минимальное значение до 0, ваше максимальное значение до 1, затем нормализует значение параметра соответственно.
Например, если вы предоставите параметры (0.2, 0.4, 0.3)
0,3 находится на полпути между 0,2 и 0,4, поэтому функция нормализует значение примерно до 0,5
Вы просто пытаетесь создать сплошной градиент чисел с 50 строками / столбцами массива, которые пересекают ребро A и ребро B?
Если так, я не знаю, является ли плавный шаг подходом.
Независимо от этого, для чего-то подобного, я бы взял физическую форму, вытащил лист бумаги и вытащил что-то вроде этого с идентификатором массива в середине и обозначил края (предполагая образец лица в кости в примере ниже):
|--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
затем увеличивайте или уменьшайте исходное значение для каждого ребра в соответствующем направлении, в зависимости от того, является ли оно минимальным или максимальным.
Если это сложнее, чем прямой градиент между краями 2D-массива, я прошу прощения, но, вероятно, потребуется лучшая визуализация того, что вы пытаетесь сделать.
Чтобы попытаться объяснить гладкость. Сначала вы начинаете с линейной интерполяции между двумя значениями, а затем изменяете ее с помощью кубической функции.
Диаграмма показывает линейную интерполяцию между 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. Если значение
Математически это кусочек кубика 3 x^2 - 2 x^3.
Моим первым инстинктом было бы применить размытие по Гауссу вдоль каждого края.