Как: инвертировать диапазон (экспоненциальный спад)?

Недавно я столкнулся со сценарием, в котором мне нужно было масштабировать значение в зависимости от расстояния между двумя объектами (камерой и целью). Первоначальная проблема заключалась в том, что камера будет прыгать слишком далеко от положения x позиционировать y двигаясь к target:

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

Первоначальная идея состояла в том, чтобы масштабировать расстояние увеличения в зависимости от того, насколько близко камера была к цели; это должно было предотвратить прохождение камерой через меш цели (или вершины в DirectX 11). Хотя в более традиционных системах для предотвращения этого используется коллайдерная система, это не традиционная система, и ее нельзя кодировать как таковую. Исходный код масштабирования был прямым:

float scale = 10000f;
if (delta < 0)
    while (target.Scale + (delta / scale) < 0)
        scale *= 10;
else
    while (target.Scale + (delta / scale) > 3)
        scale *= 10;

target.Scale += delta / scale;
target.World = Matrix.Scaling(target.Scale) * Matrix.Identity;

Несколько человек высказали несколько хороших замечаний относительно того, что попробовать, но на сегодняшний день (7/8/2018) у поста до сих пор нет рабочих ответов. Таким образом, я отказался от подхода и пришел к решению, которое работает, но по-другому.

Новая проблема: другой пользователь Stack-Overflow поделился идеей, что мне следует попробовать следующую строку кода:

Position += new Vector3(-1 * Math.Sign(e.Delta) * Math.Min(10000f, (Position.X - TargetPosition.X) / c, 0, 0));

куда c некоторая константа больше или равна двум. Это была блестящая идея; это упростило исходный код и сохранило масштабирование (что не было ответом на замедление значения, но было началом).

Это привело к тому же вопросу в другом подходе; Как я могу замедлить мою камеру, когда она приближается к цели. Ну, как я играл со значениями для c Я заметил, что чем больше c чем медленнее будет зум. Затем я начал ломать голову над тем, что я должен использовать, чтобы скорректировать значение для c, Ответ должен в значительной степени включать расстояние между камерой и целью; но проблема здесь в том, что расстояние между камерой и целью уменьшается по мере приближения, и увеличивается по мере удаления. Что приводит к:

Новый вопрос: как мне взять диапазон, такой как 3 - 1000 и инвертировать его самым простым способом, чтобы стать 1000 - 3?

1 ответ

Решение

В поисках ответа я ползла сквозь паутину. В конце концов я пришел к тому, что был готов сдаться и в итоге попросил моего друга о помощи. Через час он перезвонил мне и рассказал об экспоненциальном затухании. В своем объяснении он в значительной степени процитировал страницу Википедии:

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

Математика за этим была по существу:

c = m - ((m - 3) / 1 + Math.Exp(-10 * ((d - 100) / (r - 100))));

куда c константа нужна в вопросе, m максимальное значение для диапазона, d расстояние между камерой и целью, и r это радиус цели.

Реализация была очень простой на данный момент; Я удалил весь старый код и переписал метод как таковой:

Vector3 direction = Position - TargetPosition;
float distance = direction.Length();
float radius = 50000000f;

// Prevent the camera from entering the target.
if (distance <= radius * 1.5 && e.Delta > 0)
    return;

// Zooming out is always the same speed.
float speed = 3;
if (e.Delta > 0) {
    float t = (distance - 100) / (radius - 100);
    speed = 1000 - 997 / (1 + (float)Math.Exp(-10 * t)));
}

direction.Normalize();
Vector3 directionCopy = direction;
direction *= -(Math.Sign(e.Delta) * Math.Min(1000f, distance / speed));
Position = Position + direction;

Я хотел бы поблагодарить всех других пользователей Stack-Overflow за их помощь, и если кто-то считает, что может решить исходную проблему, не стесняйтесь дать ему шанс. Кроме того, если вы чувствуете, что у вас есть лучшее решение, не стесняйтесь поделиться им!

Другие вопросы по тегам