У меня есть код, подобный следующему в C ++:
for(int x = position.x; x < position.x + dimensions.x; ++x)
{
for(int y = position.y; y < position.y + dimensions.y; ++y)
{
glm::vec2 tc = glm::vec2(x,y);
tc -= spiralPosition;
float distance = glm::length(tc-position);
if(distance < spiralRadius)
{
float percent = (spiralRadius - distance) / spiralRadius;
float theta = percent * percent * angle;
float s = std::sin(theta);
float c = std::cos(theta);
tc = glm::vec2(glm::dot(tc,glm::vec2(c,-s)),glm::dot(tc,glm::vec2(s,c)));
}
tc += spiralPosition;
returnValues[x][y] = noise->GetValue(tc);
}
}
Что он делает, так это создает контейнер значений градиентного шума. В то время как это делает это, это также спирали результаты вокруг эпицентра, как циклон. Это основано на коде здесь, результаты выглядят одинаково:
http://www.geeks3d.com/20110428/shader-library-swirl-post-processing-filter-in-glsl/
То, что я хотел бы сделать сейчас, это расширить это в 3D, 4D, в основном ND.
Я не знаком с тригонометрией, чтобы понять, что нужно сделать. У меня есть мысль, что тангенс необходим для третьего измерения, но потом я теряюсь в том, как сделать четвертое измерение.
Может кто-нибудь указать мне некоторые статьи, которые помогут мне понять, Google на самом деле не помогает мне (но я, честно говоря, вероятно, использую неправильные условия поиска).
Ваш вопрос помечен c ++, но не ясно, какую библиотеку классов вы используете для n-мерной векторной математики, поэтому я постараюсь ответить на вопрос чисто математически, предполагая, что у вас есть классы для представления N-мерных векторов и NxN-мерных матриц. (т.е. линейные отображения из N-мерного евклидова пространства на себя).
Обобщая ваш двумерный код, алгоритм для вычисления спирального отображения становится примерно таким:
theta = percent * percent * angle;
)Шаг 4, вероятно, где вы застряли. При обобщении (ротационных) отображений на сферы размерностей N-1 необходимо учитывать Теорема о волосяном шарике, в котором говорится:
На четномерных n-сферах нет неисчезающего непрерывного касательного векторного поля.
Это означает, что для нечетномерных векторных пространств (то есть четных вложенных сфер) всегда будет хотя бы одна видимая фиксированная точка в вашем спиральном отображении, и это нельзя избежать. В вашем случае, так как вы используете ротационные отображения, будет два фиксированные точки, каждая из которых там, где выбранная вами ось вращения пересекает сферу n-1.
Теперь n-мерное спиральное отображение между первыми двумя измерениями в n-мерном евклидовом пространстве будет выглядеть (как матрица линейного преобразования NxN):
⎡cos(θ) −sin(θ) 0 . 0⎤
⎢sin(θ) cos(θ) . ⎢
S = ⎢ 0 0 1 . 0⎢
⎢ . . . . ⎢
⎣ 0 0 1⎦
Затем можно составить спиральные преобразования между последующими парами осей, чтобы получить следующую матрицу линейного преобразования NxN:
⎡cos(θ) −sin(θ) 0 0 ⎤
⎢sin(θ) cos(θ) 0 0 ⎢
⎢ 0 0 cos(θ) −sin(θ) ⎢
S = ⎢ 0 0 sin(θ) cos(θ) ⎢
⎢ . ⎢
⎢ . ⎢
⎣ 1⎦
Обратите внимание на трейлинг 1
в последней клетке? Это происходит, когда ваше N-мерное пространство имеет нечетное количество измерений, и, благодаря теореме о Волосатых шариках, не может обойтись.
В 3-х измерениях это становится спиралью вокруг оси Z:
⎡cos(θ) −sin(θ) 0⎤
S = ⎢sin(θ) cos(θ) 0⎢
⎣ 0 0 1⎦
Таким образом, если O
является центром спирали и P
точка для преобразования, общее преобразование будет:
newP = O + S(P - O)
Если вы предпочитаете вращаться вокруг другой оси, вы должны построить матрицу вращения R
принимая эту ось к оси Z, тогда общая спиральная матрица станет (R⁻¹)*S*R
, Создать матрицу вращения R
см. например Вращение одного 3-вектора на другой.