Вращающаяся линия плавно в направлении вектора (2D) - PullRequest
0 голосов
/ 13 октября 2019

Я пишу простую компьютерную анимацию, которая представляет собой линию, которая вращается вокруг фиксированной точки в центре этой линии. Величина вращения основана на алгоритме градиентного шума (шум OpenSimplex). Строка имеет начало [x, y] и номер кадра анимации. Эти три значения, включенные в шум OpenSimplex, дают значение поворота. Эта часть работает отлично.

Проблема в том, что я хочу, чтобы линия выглядела как курсор мыши, в зависимости от того, насколько далеко курсор мыши находится от линии. Курсор имеет координаты [mx, my] (которые меняются для каждого кадра анимации). Я могу легко повернуть линию и указать прямо на курсор. Но я испытываю трудности с учетом расстояния. Уточнить;линия - это вращение градиентного шума, и курсор мыши изменяет это вращение, чтобы линия (в [x, y]) указывала в [mx, my].

Кроме того, линия имеет 180-градусную идентичностьпоэтому ближайший конец должен указывать на мышь.

В основном то, что я делаю сейчас, - это "линия вращения" плюс "мышь вращения". Если он находится между 90 и 270 градусами, задняя часть линии является ближайшей к курсору, в противном случае - передней (для простоты это не включено в приведенный ниже пример кода). Затем я беру разность, множитель расстояния и вычитаю или добавляю ее к повороту линии. И это работает довольно хорошо, за исключением некоторых артефактов.

let r = OpenSimplexNoise(x, y, frame); // gives current original rotation
let frame = 68; // whichever frame
let x = 60; // some fixed coordinate of line
let y = 60; // some fixed coordinate of line
let mouseX = 10; // changes when the mouse moves
let mouseY = 10; // changes when the mouse moves
let mouseRadius = 200;
let width = 100;
let height = 1;

function distance (x, y, cx, cy) {
    return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
}

function angle (x1, y1, x2, y2) {
    let dx = x1 - x2;
    let dy = y1 - y2;

    return 360 + (Math.atan2(dy, dx) * 180 / Math.PI);
}

if (distance(x, y, mouseX, mouseY) <= mouseRadius) {
    let dist = distance(x, y, mouseX, mouseY);
    let mouseR = angle(x, y, mouseX, mouseY) % 360;

    let near = (mouseRadius - dist) / mouseRadius;
    let far = 1 - near;

    r = (r * far + near * mouseR) % 360;
}

// r now includes mouse

Живая версия: https://jsfiddle.net/Ruudt/56pk2wd1/1/

Проблема заключается в случаях, когда мышь проходит слева направо от перпендикуляра клиния (оригинальное вращение). Здесь вычисление назначит другой конец как "замыкания", затем вычислит расстояние и применяет это к вращению. Это приводит к тому, что линия переходит от направления немного влево от курсора вправо от курсора (или наоборот).

Есть ли способ исправить это?

Я сделал изображение, чтобы проиллюстрировать ситуацию.

  • Красная линия представляет линию, использующую только вращение градиентного шума
  • Черная линия - это линия, которая также включает в себя мышьположение
  • синяя дуга - значение поворота мыши (правый конец - начало координат)

поворот строки: img

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...