Frage

Ich habe gerade das zweite Jahr bei Uni abgeschlossen und einen Spielkurs absolviert. Dies hat mich immer nervt, wie Mathematik- und Spielprogramme miteinander verbunden sind. Bis jetzt habe ich benutzt Vectors, Matrices, und Quaternions In Spielen kann ich unterhalten, wie diese in Spiele passen.

Das ist ein General Question Über die Beziehung zwischen Mathematik und Programmierung für Echtzeitgrafiken bin ich gespannt, wie dynamisch die Mathematik ist. Ist es ein Fall, in dem alle Formeln und Derivate vordefiniert sind (semi definiert)?

Ist es sogar machbar, Derivate/Integrale in Echtzeit zu berechnen?

Dies sind einige Dinge, die ich nicht sehe, wie sie als Beispiel in Programmierung/Mathematik passen.

  1. MacLaurin/Talor Series Ich kann sehen, dass dies nützlich ist, aber ist es der Fall, dass Sie Ihre Funktion und seine Derivate übergeben müssen, oder können Sie ihm eine einzige Funktion übergeben und die Derivate für Sie herausarbeiten lassen?

    MacLaurin(sin(X)); or MacLaurin(sin(x), cos(x), -sin(x));
    
  2. Derivatives /Integrals Dies hängt mit dem ersten Punkt zusammen. Berechnung der y' von einer dynamischen Funktion zur Laufzeit oder ist dies etwas, das statisch mit Variablen in einer festgelegten Funktion gemacht wird.

    f = derive(x); or f = derivedX;
    
  3. Bilnear Patches Wir haben dies gelernt, um mögliche Landschaften in kleinen Stücken zu erzeugen, die zusammen "Sewen" sein könnten. Ist das etwas, was in Spielen passiert? Ich habe noch nie davon gehört (gewährt, dass mein Wissen sehr begrenzt ist) mit Verfahrensmethoden oder auf andere Weise verwendet werden. Was ich bisher getan habe, beinhaltet Arrays für verarbeitete Vertex -Informationen.

Tut mir leid, wenn dies nicht zu einem Thema ist, aber die Community hier scheint genau zu dieser Art zu sein.

Vielen Dank.

War es hilfreich?

Lösung

Die Antwort von Skizz gilt buchstäblich, aber es ist nur eine kleine Änderung erforderlich, um die Ableitung einer C ++ - Funktion zu berechnen. Wir ändern die Funktion von Skizz f zu

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

Es ist jetzt möglich, eine C ++ - Funktion zu schreiben, um die Ableitung von F in Bezug auf x zu berechnen. Hier ist ein vollständiges in sich geschlossenes Programm zur Berechnung des Derivats von f. Es ist genau (zu maschineller Präzision), da es keine ungenaue Methode wie endliche Unterschiede verwendet. Ich erkläre, wie es in einem funktioniert Papier Ich schrieb. Es verallgemeinert höhere Derivate. Beachten Sie, dass ein Großteil der Arbeiten statisch vom Compiler ausgeführt wird. Wenn Sie die Optimierung aufnehmen und Ihr Compiler anständig einbaut, sollte es so schnell sein wie alles, was Sie für einfache Funktionen von Hand schreiben könnten. (Manchmal schneller! Insbesondere ist es ziemlich gut, die Kosten für die Berechnung von F und F 'gleichzeitig zu treiben, da es dem Compiler die übliche Eliminierung der Unterexpression erleichtert, als wenn Sie separate Funktionen für F und F' schreiben.)

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;
}

Es druckt die Ergebnisse 6 und 4 wie Sie es erwarten sollten. Probieren Sie andere Funktionen aus f. Eine schöne Übung ist es, die Regeln zu erarbeiten, um Subtraktion, Teilung, Triggfunktionen usw. zu ermöglichen.

Andere Tipps

2) Derivate und Integrale werden in Echtzeit in der Regel nicht in großen Datensätzen berechnet. Es ist zu teuer. Stattdessen sind sie vorkundig. Zum Beispiel (oben auf meinem Kopf), um eine einzelne Streumedien zu rendern, Bo Sun et al. Verwenden Sie ihr "Airlight -Modell", das aus vielen algebraischen Abkürzungen besteht, um eine vorberechtigte Such -Tabelle zu erhalten.

3) Streaming großer Datensätze ist ein großes Thema, insbesondere im Gelände.

Ein Großteil der Mathematik, auf die Sie in Spielen begegnen werden, besteht darin, sehr spezifische Probleme zu lösen, und wird normalerweise einfach gehalten. Lineare Algebra wird weitaus mehr als jeder Kalkül verwendet. In Grafiken (ich mag das am meisten) stammen viele der Algorithmen aus der Erforschung der Wissenschaft, und dann werden sie von Spielprogrammierern für Geschwindigkeit geändert: Obwohl die akademische Forschung heutzutage das Ziel ihr Ziel macht.

Ich empfehle die beiden Bücher in Echtzeitkollisionserkennung und Echtzeit -Rendering, die den Eingeweide der meisten Mathematik und Konzepte enthalten, die bei der Programmierung von Game Engine verwendet werden.

Ich denke, es gibt ein grundlegendes Problem mit Ihrem Verständnis der C ++ - Sprache selbst. Funktionen in C ++ sind nicht die gleichen wie mathmatische Funktionen. In C ++ können Sie also eine Funktion definieren (die ich jetzt aufrufen werde, um Verwirrung zu vermeiden), um eine mathmatische Funktion zu implementieren:

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

In C ++ gibt es keine Möglichkeit, etwas mit der Methode F zu tun, als den Wert von F (x) für ein gegebenes x zu erhalten. Die mathmatische Funktion f (x) kann beispielsweise ganz einfach transformiert werden, f '(x), was im obigen Beispiel f' (x) = 2x+ 4. dazu in C ++ ist, müssten Sie eine Methode definieren df (x):

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

Sie können das nicht tun:

get_derivative (f(x));

und haben die Methode get_derivative Transformieren Sie die Methode f (x) für Sie.

Außerdem müssten Sie sicherstellen, dass Sie die Methode df nennen, wenn Sie die Ableitung von F nennen. Wenn Sie die Methode für die Ableitung von G versehentlich anrufen, wären Ihre Ergebnisse falsch.

Wir können jedoch die Ableitung von F (x) für ein gegebenes x annähern:

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;
}

Aber das ist sehr instabil und ziemlich ungenau.

In C ++ können Sie nun eine Klasse erstellen, die hier hilft:

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
};

und erstellen Sie unsere spezifische mathmatische Funktion:

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
};

und übergeben Sie eine Instanz dieser Klasse an eine Serienerweiterungsroutine:

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

Aber wir müssen immer noch eine Methode für die Ableitung der Funktion selbst erstellen, aber zumindest werden wir nicht versehentlich die falsche nennen.

Nun, wie andere gesagt haben, neigen die Spiele dazu, Geschwindigkeit zu bevorzugen, sodass ein Großteil der Mathematik vereinfacht wird: Interpolation, vorbereitete Tabellen usw.

Die meisten Mathematik in Spielen sind so billig wie möglich zu berechnen, und die Handelsgeschwindigkeit gegenüber Genauigkeit. Beispielsweise verwendet ein Großteil der Zahlen, die CRunching-Zahlen oder Einzelprezisionsschwimmer und nicht doppelt verwendet.

Ich bin mir nicht sicher über Ihre spezifischen Beispiele, aber wenn Sie eine billige (zur Berechnung) für ein Derivat im Voraus definieren können, ist dies der Berechnung der Dinge im laufenden Fliegen vorzuziehen.

In Spielen ist die Leistung von größter Bedeutung. Sie werden nichts finden, was dynamisch getan wird, wenn es statisch geschehen könnte, es sei denn, es führt zu einer bemerkenswerten Zunahme der visuellen Treue.

Möglicherweise interessieren Sie sich für die symbolische Differenzierung der Zeit. Dies kann (im Prinzip) mit C ++ - Vorlagen erfolgen. Keine Ahnung, ob Spiele dies in der Praxis tun (symbolische Differenzierung ist möglicherweise zu teuer, um das richtige Programm zu programmieren, und eine solche umfangreiche Vorlage verwendet in der Kompilierungszeit zu teuer, ich habe keine Ahnung).

Ich dachte jedoch, dass Sie die Diskussion über dieses Thema interessant finden könnten. Googeln "C ++ - Vorlage symbolische Derivat" gibt einige Artikel.

Es gibt viele großartige Antworten, wenn Sie an symbolischer Berechnung und Berechnung von Derivaten interessiert sind.

Nur als Vernunftprüfung ist diese Art von symbolischen (analytischen) Kalkül nicht praktisch zu Echtzeit im Kontext von Spielen.

Nach meiner Erfahrung (was mehr 3D -Geometrie in der Computer Vision als Spiele ist) sind die meisten Kalkül und Mathematik in der 3D -Geometrie, um Dinge offline vorab zu berechnen und dann zu kodieren, um diese Mathematik zu implementieren. Es ist sehr selten, dass Sie die Dinge symbolisch im laufenden Fliegen berechnen und dann auf diese Weise analytische Formeln im Laufe der Fliege bekommen müssen.

Können Spielprogrammierer überprüfen?

1), 2)

Die Maclaurin/Taylor -Reihe (1) werden in jedem Fall aus Derivaten (2) konstruiert.

Ja, es ist unwahrscheinlich, dass Sie zur Laufzeit symbolisch eine davon berechnen müssen - aber sicher sicher User207442Die Antwort ist großartig, wenn Sie sie brauchen.

Was Sie finden, ist, dass Sie eine mathematische Berechnung durchführen müssen und dass Sie sie in angemessener Zeit oder manchmal sehr schnell tun müssen. Dazu müssen Sie auch dann, wenn Sie die Lösungen anderer verwenden, die grundlegende Analyse verstehen.

Wenn Sie das Problem selbst lösen müssen, ist der Aufwärtstrend, dass Sie oft nur eine ungefähre Antwort benötigen. Dies bedeutet, dass Sie beispielsweise eine Serientyp -Expansion durchaus ermöglichen können, eine komplexe Funktion auf eine einfache lineare oder quadratische Funktion zu reduzieren, die sehr schnell ist.

Für Integrale können Sie das Ergebnis oft numerisch berechnen, aber es wird immer sein viel langsamer als eine analytische Lösung. Der Unterschied kann durchaus der Unterschied zwischen praktisch oder nicht sein.

Kurz gesagt: Ja, Sie müssen die Mathematik lernen, aber um das Programm zu schreiben, anstatt das Programm für Sie zu tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top