Вопрос

Я только что закончил второй год в Uni, проходя курс игры, это всегда беспокоит меня, как связаны математические и игровые программы. До сих пор я использовал Vectors, Matrices, а также Quaternions В играх я могу под Stand, как они вписываются в игры.

Это General Question Что касается отношений между математикой и программированием для графики в реальном времени, мне любопытно, насколько динамична математика. Это тот случай, когда все формулы и производные предопределены (полу -полу)?

Возможно ли вычислять производные/интегралы в режиме реального времени?

Вот некоторые из вещей, которые я не вижу в том, как они вписываются в программирование/математику в качестве примера.

  1. MacLaurin/Talor Series Я вижу, что это полезно, но это тот случай, когда вы должны выполнить свою функцию и ее производные, или вы можете передать ее одну функцию и заставить ее разрабатывать деривативы для вас?

    MacLaurin(sin(X)); or MacLaurin(sin(x), cos(x), -sin(x));
    
  2. Derivatives /Integrals Это связано с первым пунктом. Расчет y' функции, выполненной динамически во время выполнения или это то, что статически выполняется, возможно, с переменными внутри установленной функции.

    f = derive(x); or f = derivedX;
    
  3. Bilnear Patches Мы узнали об этом как способ, чтобы создать пейзажи в небольших кусках, которые могут быть «шить» вместе, это то, что происходит в играх? Я никогда не слышал об этом (предоставленный мои знания очень ограничены) используются с процедурными методами или иным образом. То, что я сделал до сих пор, включает в себя массивы для обработки информации вершины.

Извините, если это не по теме, но сообщество здесь кажется точным, по этому поводу.

Спасибо.

Это было полезно?

Решение

Ответ Skizz верен, когда принимается буквально, но требуется лишь небольшое изменение, чтобы сделать возможным вычисление производной функции C ++. Мы изменяем функцию Skizz f к

template<class Float> f (Float x)
{
  return x * x + Float(4.0f) * x + Float(6.0f); // f(x) = x^2 + 4x + 6
}

Теперь можно написать функцию C ++, чтобы вычислить производную F в отношении x. Вот полная автономная программа по вычислению производной f. Это точное (с точностью машины), поскольку он не использует неточный метод, такой как конечные различия. Я объясняю, как это работает в бумага Я написал. Он обобщает на более высокие производные. Обратите внимание, что большая часть работы выполняется статически компилятором. Если вы приведете оптимизацию, и ваш компилятор вновь встроит, это должно быть так же быстро, как и все, что вы можете написать вручную для простых функций. (Иногда быстрее! В частности, это довольно хорошо для амортизации стоимости вычисления F и F 'одновременно, потому что это облегчает устранение общей субэкспрессии компилятором, чем если вы пишете отдельные функции для F и F'.)

using namespace std;

template<class Float>
Float f(Float x)
{
  return x * x + Float(4.0f) * x + Float(6.0f);
}

struct D
{
  D(float x0, float dx0 = 0) : x(x0), dx(dx0) { }
  float x, dx;
};

D operator+(const D &a, const D &b)
{
  // The rule for the sum of two functions.
  return D(a.x+b.x, a.dx+b.dx);
}

D operator*(const D &a, const D &b)
{
  // The usual Leibniz product rule.
  return D(a.x*b.x, a.x*b.dx+a.dx*b.x);
}

// Here's the function skizz said you couldn't write.
float d(D (*f)(D), float x) {
  return f(D(x, 1.0f)).dx;
}

int main()
{
  cout << f(0) << endl;
  // We can't just take the address of f. We need to say which instance of the
  // template we need. In this case, f<D>.
  cout << d(&f<D>, 0.0f) << endl;
}

Он печатает результаты 6 а также 4 как вы должны ожидать. Попробуйте другие функции f. Анкет Хорошее упражнение - попытаться выработать правила, позволяющие вычитать вычитание, деление, функции тригера и т. Д.

Другие советы

2) Производные и интегралы обычно не рассчитываются на больших наборах данных в режиме реального времени, это слишком дорого. Вместо этого они предварительно рассчитываются. Например (в верхней части моей головы), чтобы отобразить один разбросанный средний, Bo Sun et al. Используйте их «модель Airlight», которая состоит из множества алгебраических ярлыков, чтобы получить предварительно рассчитанную таблицу поиска.

3) потоковая передача больших наборов данных является большой темой, особенно в местности.

Многие математики, с которыми вы столкнетесь в играх, - это решить очень конкретные проблемы и обычно сохраняется простым. Линейная алгебра используется гораздо больше, чем любое исчисление. В графике (мне больше всего нравится) многие алгоритмы поступают из исследований, проведенных в академических кругах, а затем они изменяются для скорости игровыми программистами: хотя даже академические исследования делают скорость своей цели в наши дни.

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

Я думаю, что есть фундаментальная проблема с вашим пониманием самого языка C ++. Функции в C ++ не совпадают с математическими функциями. Таким образом, в C ++ вы можете определить функцию (которую я теперь позвоню, чтобы избежать путаницы) для реализации математической функции:

float f (float x)
{
  return x * x + 4.0f * x + 6.0f; // f(x) = x^2 + 4x + 6
}

В C ++ нет никакого способа сделать что -либо с методом F, кроме как получить значение f (x) для данного x. Математическая функция f (x) может быть легко преобразована довольно легко, например, f '(x), который в примере приведенного выше - f' (x) = 2x+ 4. Чтобы сделать это в C ++, вам нужно определить метод DF (x):

float df (float x)
{
  return 2.0f * x + 4.0f; //  f'(x) = 2x + 4
}

Вы не можете сделать это:

get_derivative (f(x));

и иметь метод get_derivative Преобразовать метод F (x) для вас.

Кроме того, вы должны были бы убедиться, что, когда вы хотите производную F, который вы называете методом DF. Если бы вы вызвали метод для производного G в случайном случае, ваши результаты будут неправильными.

Мы можем, однако, аппроксимировать производную f (x) для данного x:

float d (float (*f) (float x), x) // pass a pointer to the method f and the value x
{
  const float epsilon = a small value;
  float dy = f(x+epsilon/2.0f) - f(x-epsilon/2.0f);
  return epsilon / dy;
}

Но это очень нестабильно и довольно неточно.

Теперь в C ++ вы можете создать класс, чтобы помочь здесь:

class Function
{
public:
  virtual float f (float x) = 0; // f(x)
  virtual float df (float x) = 0; // f'(x)
  virtual float ddf (float x) = 0; // f''(x)
  // if you wanted further transformations you'd need to add methods for them
};

и создайте нашу конкретную математическую функцию:

class ExampleFunction : Function
{
  float f (float x) { return x * x + 4.0f * x + 6.0f; } // f(x) = x^2 + 4x + 6 
  float df (float x) { return 2.0f * x + 4.0f; } //  f'(x) = 2x + 4
  float ddf (float x) { return 2.0f; } //  f''(x) = 2
};

и передайте экземпляр этого класса в программу расширения серии:

float Series (Function &f, float x)
{
   return f.f (x) + f.df (x) + f.ddf (x); // series = f(x) + f'(x) + f''(x)
}

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

Теперь, как говорили другие, игры, как правило, способствуют скорости, поэтому большая часть математики упрощена: интерполяция, предварительно вычислимые таблицы и т. Д.

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

Не уверен в ваших конкретных примерах, но если вы можете определить дешевую (для расчета) формулу для производной заранее, то это предпочтительнее расчета вещей на лету.

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

Вы можете быть заинтересованы в символической дифференциации времени компиляции. Это может (в принципе) быть сделано с помощью шаблонов C ++. Понятия не имею, что игры делают это на практике (символическая дифференциация может быть слишком дорогой, чтобы программировать правильное, и такое обширное использование шаблонов может быть слишком дорогим во время компиляции, я понятия не имею).

Однако я думал, что вы можете найти обсуждение этой темы интересной. Googling "C ++ Шаблон символического производного" дает несколько статей.

Есть много замечательных ответов, если вы заинтересованы в символическом расчете и вычислении производных.

Однако, как и проверка здравомыслия, этот вид символического (аналитического) исчисления не практично в режиме реального времени в контексте игр.

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

Могут ли какие -нибудь игровые программисты проверить?

1), 2)

Серия Maclaurin/Taylor (1) построена из производных (2) в любом случае.

Да, вам вряд ли нужно будет символически вычислить любой из них во время выполнения - но наверняка user207442Ответ великолепен, если вам это нужно.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top