Spielephysik (game physics): Tageszeitänderungen (scheinbare Sonnenbahnen)

Bevor wir mit der Simulation von Tageszeitänderungen beginnen können, müssen wir uns zuvor mit einem anderen Problem befassen – die wechselseitige Umrechnung von Simulationszeit und Uhrzeit.
Die Simulationszeit bemisst sich normalerweise in Sekunden. Da die Uhrzeit jedoch in Stunden, Minuten und Sekunden angegeben wird, benötigen wir eine Formel für die Umrechnung der Uhrzeit in Simulationszeit:

ActualTime = (float)Seconds + (float)Hours*3600.0f + (float)Minutes*60.0f;

Bei Umrechnung der Simulationszeit in Uhrzeit muss man zunächst beachten, dass nach jeweils 86400 Sekunden (entspricht 24 Stunden) ein neuer Tag beginnt. Um die aktuelle Stunde zu ermitteln, muss man die Simulationszeit lediglich durch 3600 teilen (jede Stunde hat 3600 Sekunden) und den Nachkommateil verwerfen. Um die Minutenzeit zu bestimmen, berechnet man die Differenz aus der Simulationszeit und der Stundenzeit (angegeben in Sekunden) und dividiert das Ergebnis dann durch 60 (eine Minute hat 60 Sekunden). Die restlichen Sekunden erhält man, indem man von der Simulationszeit sowohl die Stunden- als auch die Minutenzeit (beides angegeben in Sekunden) abzieht:

// nach 24 Stunden beginnt ein neuer Tag:
if(ActualTime > 86400.0f)
    ActualTime -= 86400.0f;

Hours   = (long)(ActualTime/3600.0f);
Minutes = (long)((ActualTime-Hours*3600.0f)/60.0f);
Seconds = (long)ActualTime-Hours*3600-Minutes*60;


Die scheinbaren Bahnen der Sonne

Auf den ersten Blick scheint die Simulation von Tageszeitänderungen trivial zu sein – schon im Kindesalter lernen wir, dass die Sonne im Osten aufgeht, zur Mittagszeit im Süden steht und im Westen wieder unterght. Mehr muss man doch eigentlich gar nicht wissen oder? Nun ja, zum einen ist die (scheinbare) Sonnenbahn abhängig von der jeweiligen Jahreszeit und zum anderen nehmen Beobachter auf unterschiedlichen Breitengraden (latitude) unterschiedliche Sonnenbahnen wahr. Erschwerend kommt hinzu, dass auch die vorherrschende Jahreszeit an einem Ort breitengradabhängig ist – wenn auf der Nordhalbkugel der Sommer beginnt, dann setzt auf der Südhalbkugel der Winter ein und umgekehrt.

Hinweis:
Man spricht von scheinbaren Sonnenbahnen, weil sich in der Tat nicht die Sonne bewegt sondern die Erde.

Zusammenfassend lässt sich feststellen, dass die Sache mit den Tageszeitänderungen und den Sonnenbahnen alles andere als trivial zu sein scheint.

Um ein wenig Ordnung ins Chaos zu bringen, betrachten wir uns einmal die Sonnenbahnen an zwei ausgezeichneten Breitengraden – am Äquator (Breitengrad 0°) sowie am Nordpol (Breitengrad 90°). Skizziert sind jeweils die drei Sonnenbahnen, die ein Beobachter am Tag des Frühlings- (21. März) bzw. Herbstanfangs (23. September), am Tag der Winter- (21. Dezember) und am Tag der Sommer-Sonnenwende (21. Juni) beobachten würde.

Hinweis:
Ursache für die Wanderung der Sonnenbahn im Verlauf des Jahres ist die Neigung der Erdachse/Rotationsachse (axial Tilt) um 23,5°. Wäre die Rotationsachse stattdessen senkrecht zur Bewegungsrichtung der Erde orientiert (Neigung der Erdachse um 0°), dann gäbe es keine wechselnden Jahreszeiten, da sich der Einfallswinkel der Sonnenstrahlen im Verlauf des Jahres auf einem Breitenkreis zu einer festgelegten Uhrzeit niemals ändern würde.

Sonnenbahnen am Äquator:














Die Bahnen der Sonne und Sterne verlaufen am Äquator senkrecht zum Horizont. Dies führt zu abrupten Tag-Nacht-Wechseln mit extrem kurzen Dämmerungszeiten. Die maximale Sonnenhöhe zur Mittagszeit beträgt 90°. An den Sonnenwend-Tagen beträgt die Mittagssonnenhöhe aufgrund der Erdachsen-Neigung lediglich 66,5° (90°-23.5°).

Sonnenbahnen am Nordpol:















Im Sommer geht am Nordpol die Sonne niemals unter. Der Tag (Polartag) ist folglich ein halbes Jahr lang. Im Winter geht die Sonne erst gar nicht auf; man bezeichnet diese Jahreszeit daher auch als Polarnacht. Am Tag der Sommer-Sonnenwende entspricht die maximale Sonnenstandshöhe mit einem Winkel von 23,5° der Neigung der Erdachse. Die niedrigste Sonnenstandshöhe mit einem Winkel von -23,5° wird am Tag der Winter-Sonnenwende erreicht.

Berechnung der Sonnenbahnen unter Vernachlässigung der Neigung der Erdachse:

Zunächst einmal werden wir die Sonnenbahnen unter Vernachlässigung der Neigung der Erdachse berechnen. Den Abbildungen entsprechend sind dies die Bahnen am Tag des Frühlings- (21. März) bzw. Herbstanfangs (23. September). Die Rotationsachse der Sonne berechnet sich in Abhängigkeit vom Breitengrad (latitude) wie folgt:

// Winkel der Sonnenrotationsachse:
float HorizontalAngle, VerticalAngle;

// Sonnenrotationsachse:
D3DXVECTOR3 SunRotationAxis;

HorizontalAngle = 90.0f*D3DX_PI/180.0f;
VerticalAngle   = latitude*D3DX_PI/180.0f;

SunRotationAxis.x = cos(VerticalAngle)*sin(HorizontalAngle);
SunRotationAxis.y = sin(VerticalAngle);
SunRotationAxis.z = cos(VerticalAngle)*cos(HorizontalAngle);

In Übereinstimmung mit den Abbildungen berechnet sich für den Nordpol (latitude = 90°) eine Rotationsachse von (0, 1, 0) und für den Äquator (latitude = 0°) eine Rotationsachse von (1, 0, 0).

Unter der Annahme, dass sich die Sonne in 24 Stunden (86400 Sekunden) einmal um die Rotationsachse dreht (Drehwinkel = 2PI), ergibt sich ein Drehwinkel pro Sekunde von:

float SolarRotation_PerSecond = 2.0f*D3DX_PI/86400.0f;

Bei der Berechnung der Richtung (SunDirectionUncorrected), in der ein Beobachter die Sonne wahrnehmen würde (kurz Sonnenstand), machen wir uns den Fakt zunutze, dass die Sonne am Äquator exakt im Westen – mit anderen Worten in Richtung (0, 0, 1) – um exakt 18 Uhr untergeht:

// Sonnenstand ohne Berücksichtigung der Erdachsenneigung:
D3DXVECTOR3
SunDirectionUncorrected;

// 64800.0f enspricht 18 Uhr, untergehende Sonne steht im Westen
// (z-Richtung):

float ActualSolarRotationAngle = SolarRotation_PerSecond*(ActualTime -
                                 64800.0f);

D3DXMATRIXA16
SunRotationMatrix;

D3DXMatrixRotationAxis(&
SunRotationMatrix, &SunRotationAxis,
                       ActualSolarRotationAngle);

// Sonnenstand aus der Rotationsmatrix auslesen:
SunDirectionUncorrected.x =
SunRotationMatrix._31;
SunDirectionUncorrected.y =
SunRotationMatrix._32;
SunDirectionUncorrected.z =
SunRotationMatrix._33;


Korrektur der Sonnenbahnen durch Berücksichtigung der Neigung der Erdachse:

Ohne Neigung der Erdachse würden die beobachteten Sonnenbahnen lediglich vom Breitengrad abhängig sein. Jahreszeiten gäbe es nicht, da sich die Bahnen im Verlauf des Jahres niemals ändern würden. Die Neigung der Erdachse (AxialTilt) von 23,5° führt jedoch dazu, dass sich die Sonnenstände im Verlauf des Jahres zu einer bestimmten Uhrzeit in einem Winkelbereich von -23.5° bis +23.5° ändern, was wir bereits anhand zweier Abbildungen einmal für den Nordpol und einmal für den Äquator veranschaulicht haben. Die Physiker sprechen hierbei von der sogenannten Sonnen-Deklination. Nimmt man zur Vereinfachung an, dass sich die Erde auf einer kreisförmigen Bahn um die Sonne bewegt, dann berechnet sich die Deklination als Funktion des Tages näherungsweise wie folgt:

SolarDeclination = AxialTilt * sin(0.017f*(NrOfDay-80));

Anhand von drei Beispielen lässt sich diese Formel wie folgt veranschaulichen:

Beispiel 1:
Am Tag des Frühlingsanfangs – dem 21. März (Tag 80) – erwarten wir gemäß unseren Abbildungen eine Deklination von 0°:

AxialTilt * sin(0.017f*(80-80)) = AxialTilt * sin(0.017f*0) = 0

Beispiel 2:
Am 21. Juni (Tag 172) – dem Tag der Sommer-Sonnenwende – beträgt die Deklination hingegen 23,5°:

AxialTilt * sin(0.017f*(172-80)) = AxialTilt * sin(0.017f*92) =
AxialTilt * sin(0.5*PI) = AxialTilt

Beispiel 3:
Am Tag des Herbstanfangs – dem 23. September (Tag 266) – erwarten wir gemäß unseren Abbildungen wiederum eine Deklination von 0°:

AxialTilt * sin(0.017f*(266-80)) = AxialTilt * sin(0.017f*186) =
AxialTilt * sin(PI) = 0

Die Korrektur des Sonnenstands ist nun alles andere als kompliziert, sie entspricht lediglich einer Drehung des unkorrigierten Sonnenstands (SunDirectionUncorrected) um den tagesabhängigen Sonnen-Deklinationswinkel. Der eigentliche Trick besteht in der Berechnung der Rotationsachse (RotationAxis), um welche die Korrekturdrehung erfolgt:

// Rotationsachse für die Korrektur des Sonnenstands:
D3DXVECTOR3 RotationAxis;

D3DXVec3Cross(&RotationAxis, &
SunRotationAxis,
              &SunDirectionUncorrected);

D3DXVec3Normalize(&RotationAxis, &RotationAxis);

// Rotationsmatrix für die Korrektur des Sonnenstands:
D3DXMATRIXA16 SunHeightCorrectionMatrix
;

D3DXMatrixRotationAxis(&SunHeightCorrectionMatrix, &RotationAxis,
                       SolarDeclination);

// Der korrekte Sonnenstand ergibt sich durch eine einfache Drehung
// des unkorrigierten Sonnenstands:
Multiply3DVectorWithRotationMatrix(&SunDirection,
                                   &SunDirectionUncorrected,
                                   &SunHeightCorrectionMatrix);