Im ersten Schritt wird die maximal mögliche Anzahl der Sterne
innerhalb der zu generierenden Galaxie berechnet, sowie die Startposition festgelegt,
von der aus die Positionierung der einzelnen Sterne beginnt.
long
NumSunsMax = g_NumSunsMaxXDir*g_NumSunsMaxYDir*g_NumSunsMaxZDir;
D3DXVECTOR3* StellarPosition = new D3DXVECTOR3[NumSunsMax];
bool*
UseStellarPosition = new bool[NumSunsMax];
D3DXVECTOR3 CenterPos = g_NullVector;
D3DXVECTOR3 DiffVector;
D3DXVECTOR3 StartPos = D3DXVECTOR3(
-0.5f*(g_NumSunsMaxXDir-1)*g_GalaxyParam_DeltaX,
-0.5f*(g_NumSunsMaxYDir-1)*g_GalaxyParam_DeltaY,
-0.5f*(g_NumSunsMaxZDir-1)*g_GalaxyParam_DeltaZ);
Alle Sterne werden zunächst unter Berücksichtigung der g_GalaxyParam_DeltaX/Y/Z-Parameter
in gleichmäßigen Abständen im Raum positioniert. Um die regelmäßige Anordnung
der Sterne aufzubrechen, werden die einzelnen Stern-zu-Stern-Abstände in einem
zweiten Schritt mithilfe der Min/MaxVarianceX/Y/Z-Parameter
nach dem Zufallsprinzip variiert.
long i;
long
counter = 0;
float
distance;
float
maxDistance = g_GalaxyDistanceDecreaseParameter3*
D3DXVec3Length(&StartPos);
float varX;
float varY;
float varZ;
for(i =
0; i < g_NumSunsMaxXDir; i++)
{
for(j =
0; j < g_NumSunsMaxYDir; j++)
{
for(k =
0; k < g_NumSunsMaxZDir; k++)
{
if(lrnd(2, 4) == 2)
varX = frnd(0.5f*g_GalaxyParam_MaxVarianceX,
g_GalaxyParam_MaxVarianceX);
else
varX = frnd(g_GalaxyParam_MinVarianceX,
0.5f*g_GalaxyParam_MinVarianceX);
if(lrnd(2, 4) == 2)
varY = frnd(0.5f*g_GalaxyParam_MaxVarianceY,
g_GalaxyParam_MaxVarianceY);
else
varY = frnd(g_GalaxyParam_MinVarianceY,
0.5f*g_GalaxyParam_MinVarianceY);
if(lrnd(2, 4) == 2)
varZ = frnd(0.5f*g_GalaxyParam_MaxVarianceZ, g_GalaxyParam_MaxVarianceZ);
else
varZ = frnd(g_GalaxyParam_MinVarianceZ,
0.5f*g_GalaxyParam_MinVarianceZ);
StellarPosition[counter] = StartPos +
D3DXVECTOR3(i*g_GalaxyParam_DeltaX,
D3DXVECTOR3(i*g_GalaxyParam_DeltaX,
j*g_GalaxyParam_DeltaY,
k*g_GalaxyParam_DeltaZ)+
D3DXVECTOR3(varX, varY, varZ);
UseStellarPosition[counter] = true;
counter++;
}}}
Im Anschluss daran erfolgt mithilfe der DistanceDecrease-Parameter
eine Modifikation der Sternendichte und Größe der Galaxie durch Aussortieren
einer mehr oder weniger großen Anzahl von Sternen (UseStellarPosition[i] = false).
counter = 0;
float
randomValue;
float
quotient;
for(i =
0; i < NumSunsMax; i++)
{
DiffVector =
StellarPosition[i] - CenterPos;
distance =
D3DXVec3Length(&DiffVector);
randomValue
= frnd(0.0f, 1.0f);
quotient =
distance/maxDistance;
if(randomValue >= 1.0f-
pow(quotient,g_GalaxyDistanceDecreaseParameter1*
pow(1.0f-quotient,g_GalaxyDistanceDecreaseParameter2)))
{
UseStellarPosition[i] = false;
}
else
counter++;
}
Im nächsten Schritt werden die Spiralarme der Galaxie
generiert. Hierbei wird zunächst überprüft, ob die zuvor positionierten Sterne
innerhalb oder außerhalb des galaktischen Bulge (Ausbuchtung des Kernbereichs) liegen. Für alle Sterne
innerhalb des Bulges wird lediglich der Abstand zum Zentrum der Galaxie
mithilfe der beiden DistanceIncreaseFactor-Parameter
korrigiert. Die übrigen Sterne werden zunächst entlang der Spiralarm-Richtungen
neu positioniert. Zusätzlich dazu wird der Abstand der Sterne von der
galaktischen Ebene unter Berücksichtigung des g_SpiralGalaxyFlatnessFactor-Parameters mit zunehmender
Entfernung vom galaktischen Zentrum verringert.
Die endgültigen Sternenpositionen in den einzelnen
Spiralarmen ergeben sich durch Drehungen der zuvor festgelegten Positionen um
die galaktische Achse, sofern man die Drehwinkel unter Berücksichtigung der beiden Parameter g_SpiralGalaxyTwistingFactorMin sowie g_SpiralGalaxyTwistingFactorMax mit zunehmendem Abstand vom galaktischen Zentrum kontinuierlich vergrößert.
Generierung einer
Galaxie mit 4 Spiralarmen:
D3DXVECTOR3 DiffVectorRotated;
D3DXMATRIXA16 RotationMatrix;
D3DXVECTOR3 GalacticAxis;
// Vektoren für
die Beschreibung der galaktischen Ebene:
D3DXVec3Cross(&GalacticAxis,
&SpiralGalaxyPlaneDirection1,
&SpiralGalaxyPlaneDirection2);
float
dot1, dot2, dot3;
float
distanceFactor;
long
randomDir;
if(g_NumOfSpiralArms ==
4)
{
for(i =
0; i < NumSunsMax; i++)
{
if(UseStellarPosition[i]
== true)
{
DiffVector = StellarPosition[i] - CenterPos;
dot1 = D3DXVec3Dot(&DiffVector, &SpiralGalaxyPlaneDirection1);
dot2 = D3DXVec3Dot(&DiffVector,
&SpiralGalaxyPlaneDirection2);
dot3 = D3DXVec3Dot(&DiffVector,
&GalacticAxis);
distance = sqrtf(dot1*dot1 + dot2*dot2);
// Stern innerhalb des Bulge:
if(distance <
g_SpiralGalaxyBulgeRadius)
{
distanceFactor =
pow(distance,g_SpiralGalaxyDistanceExponent);
DiffVector *=
pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVector + CenterPos;
continue;
}
// Stern außerhalb des Bulge:
randomDir = lrnd(0, 4);
if(randomDir == 0)
{
DiffVector = SpiralGalaxyPlaneDirection1*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir == 1)
{
DiffVector = -SpiralGalaxyPlaneDirection1*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir == 2)
{
DiffVector = SpiralGalaxyPlaneDirection2*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir == 3)
{
DiffVector = -SpiralGalaxyPlaneDirection2*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
distanceFactor =
pow(distance,g_SpiralGalaxyDistanceExponent);
CalcRotAxisMatrix(&RotationMatrix,
&GalacticAxis,
frnd(g_SpiralGalaxyTwistingFactorMin,
g_SpiralGalaxyTwistingFactorMax)*distanceFactor);
Multiply3DVectorWithRotationMatrix(&DiffVectorRotated,
&DiffVector,
&RotationMatrix);
DiffVectorRotated *= pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVectorRotated + CenterPos;
}}}
Generierung einer
Galaxie mit 3 Spiralarmen:
else if(g_NumOfSpiralArms
== 3)
{
D3DXVECTOR3 ThreeSpiralArmsDirection2;
D3DXVECTOR3 ThreeSpiralArmsDirection3;
CalcRotAxisMatrix(&RotationMatrix, &GalacticAxis,
120.0f*g_PI/180.0f);
Multiply3DVectorWithRotationMatrix(&ThreeSpiralArmsDirection2,
&ThreeArmedSpiralGalaxyBaseDirection,
&RotationMatrix);
Multiply3DVectorWithRotationMatrix(&ThreeSpiralArmsDirection3,
&ThreeSpiralArmsDirection2,
&RotationMatrix);
for(i = 0; i < NumSunsMax;
i++)
{
if(UseStellarPosition[i] == true)
{
DiffVector = StellarPosition[i] - CenterPos;
dot1 = D3DXVec3Dot(&DiffVector, &SpiralGalaxyPlaneDirection1);
dot2 = D3DXVec3Dot(&DiffVector, &SpiralGalaxyPlaneDirection2);
dot3 = D3DXVec3Dot(&DiffVector, &GalacticAxis);
distance = sqrtf(dot1*dot1 + dot2*dot2);
// Stern innerhalb des Bulge:
if(distance <
g_SpiralGalaxyBulgeRadius)
{
distanceFactor = pow(distance, g_SpiralGalaxyDistanceExponent);
DiffVector *= pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVector + CenterPos;
continue;
}
// Stern außerhalb des Bulge:
randomDir = lrnd(0, 3);
if(randomDir == 0)
{
DiffVector = ThreeArmedSpiralGalaxyBaseDirection*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir
== 1)
{
DiffVector = ThreeSpiralArmsDirection2*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir
== 2)
{
DiffVector = ThreeSpiralArmsDirection3*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
distanceFactor = pow(distance, g_SpiralGalaxyDistanceExponent);
CalcRotAxisMatrix(&RotationMatrix, &GalacticAxis,
frnd(g_SpiralGalaxyTwistingFactorMin,
g_SpiralGalaxyTwistingFactorMax)*distanceFactor);
Multiply3DVectorWithRotationMatrix(&DiffVectorRotated,
&DiffVector,
&RotationMatrix);
DiffVectorRotated *= pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVectorRotated + CenterPos;
}}}
Generierung einer
Galaxie mit 2 Spiralarmen:
else //
if(g_NumOfSpiralArms == 2)
{
for(i =
0; i < NumSunsMax; i++)
{
if(UseStellarPosition[i]
== true)
{
DiffVector = StellarPosition[i] - CenterPos;
dot1 = D3DXVec3Dot(&DiffVector,
&SpiralGalaxyPlaneDirection1);
dot2 = D3DXVec3Dot(&DiffVector,
&SpiralGalaxyPlaneDirection2);
dot3 = D3DXVec3Dot(&DiffVector,
&GalacticAxis);
distance = sqrtf(dot1*dot1 + dot2*dot2);
// Stern innerhalb des Bulge:
if(distance <
g_SpiralGalaxyBulgeRadius)
{
distanceFactor = pow(distance,g_SpiralGalaxyDistanceExponent);
DiffVector *= pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVector + CenterPos;
continue;
}
// Stern außerhalb des Bulge:
randomDir = lrnd(0, 2);
if(randomDir == 0)
{
DiffVector = SpiralGalaxyPlaneDirection1*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
else if(randomDir == 1)
{
DiffVector = -SpiralGalaxyPlaneDirection1*distance +
(g_SpiralGalaxyFlatnessFactor*dot3)*GalacticAxis;
}
distanceFactor = pow(distance,g_SpiralGalaxyDistanceExponent);
CalcRotAxisMatrix(&RotationMatrix,
&GalacticAxis,
frnd(g_SpiralGalaxyTwistingFactorMin,
g_SpiralGalaxyTwistingFactorMax)*distanceFactor);
Multiply3DVectorWithRotationMatrix(&DiffVectorRotated,
&DiffVector,
&RotationMatrix);
DiffVectorRotated *= pow(g_GalaxyStellarDistanceIncreaseFactor1,
g_GalaxyStellarDistanceIncreaseFactor2*distance);
StellarPosition[i] = DiffVectorRotated + CenterPos;
}}}
pGalaxy->Set_NumSunsMax(counter);
Im letzten Schritt wird für jeden Stern der Sternentyp sowie seine Größe festgelegt. Zur Auswahl stehen hierbei die folgenden
Sternentypen und Spektralklassen:
- Roter Riese (Spektralklasse M)
- Roter Zwerg (Spektralklasse M)
- Oranger Stern (Spektralklasse K)
- Gelber Stern (Spektralklasse G)
- Weißer Stern (Spektralklasse F)
- Blauer Riese (Spektralklasse B)
- Blauer Überriese (Spektralklasse O)
float RandomSpectralValue;
long SpectralType;
float SunScale;
for(i = 0; i < NumSunsMax;
i++)
{
if(UseStellarPosition[i] == true)
{
RandomSpectralValue = frnd(0.0f, 1.0);
if(RandomSpectralValue >=
g_SunBlue_DistributionValueMin &&
RandomSpectralValue <
g_SunBlue_DistributionValueMax)
{
SpectralType = 0;
SunScale =
frnd(g_SunBlue_MinScale, g_SunBlue_MaxScale);
}
else if(RandomSpectralValue
>= g_SunOrange_DistributionValueMin &&
RandomSpectralValue < g_SunOrange_DistributionValueMax)
{
SpectralType = 1;
SunScale =
frnd(g_SunOrange_MinScale, g_SunOrange_MaxScale);
}
else if(RandomSpectralValue
>= g_SunRedDwarf_DistributionValueMin &&
RandomSpectralValue
< g_SunRedDwarf_DistributionValueMax)
{
SpectralType = 2;
SunScale =
frnd(g_SunRedDwarf_MinScale, g_SunRedDwarf_MaxScale);
}
else if(RandomSpectralValue
>= g_SunRedGiant_DistributionValueMin &&
RandomSpectralValue < g_SunRedGiant_DistributionValueMax)
{
SpectralType = 3;
SunScale =
frnd(g_SunRedGiant_MinScale, g_SunRedGiant_MaxScale);
}
else if(RandomSpectralValue
>= g_SunYello_DistributionValueMin &&
RandomSpectralValue <
g_SunYello_DistributionValueMax)
{
SpectralType = 4;
SunScale =
frnd(g_SunYello_MinScale, g_SunYello_MaxScale);
}
else if(RandomSpectralValue
>= g_SunWhite_DistributionValueMin &&
RandomSpectralValue <
g_SunWhite_DistributionValueMax)
{
SpectralType = 5;
SunScale =
frnd(g_SunWhite_MinScale, g_SunWhite_MaxScale);
}
else if(RandomSpectralValue
>= g_SunBlueGiant_DistributionValueMin &&
RandomSpectralValue < g_SunBlueGiant_DistributionValueMax)
{
SpectralType = 6;
SunScale = frnd(g_SunBlueGiant_MinScale,
g_SunBlueGiant_MaxScale);
}
else if(RandomSpectralValue
>= g_SunBlueHyperGiant_DistributionValueMin &&
RandomSpectralValue < g_SunBlueHyperGiant_DistributionValueMax)
{
SpectralType = 7;
SunScale = frnd(g_SunBlueHyperGiant_MinScale, g_SunBlueHyperGiant_MaxScale);
}
else
{
SpectralType = 4;
SunScale =
frnd(g_SunYello_MinScale, g_SunYello_MaxScale);
}
pGalaxy->Init_Sun(&StellarPosition[i], SunScale, SpectralType);
}}