2016-01-09 33 views
5

Próbuję zbudować symulację układu słonecznego w opengl za pomocą C. Nie mogę wymyślić, jak napisać kod do obliczania kierunku siły wywieranej na planeta przez inną. To, co mam do tej pory:obliczyć kierunek siły przyciągania między planetami

void attraction(planet self, planet other, float *direction) 
{ 
    float d = vecDistance(self.p, other.p); 

    //calc the force of attraction 
    float f = G * ((self.mass * other.mass)/(pow(d, 2))); 

    //calc the direction of the force 
    float vectorDist[3]; 
    vecSub(self.p, other.p, vectorDist); 

    direction[0] = f*vectorDist[0]/d; 
    direction[1] = f*vectorDist[1]/d; 
    direction[2] = f*vectorDist[2]/d; 
} 



float vecDistance(float *pV1, float *pV2) 
{ 
    float fLen=0.0f; 

    if(pV1 && pV2) 
    { 
     float av[3]; 

     vecSub(pV2, pV1, av); 
     fLen=vecLength(av); 
    } 

    return fLen; 
} 


void vecSub(float *pV0, float *pV1, float *pVRes) 
{ 
    if(pV0 && pV1 && pVRes) 
    { 
     pVRes[0]=pV0[0]-pV1[0]; 
     pVRes[1]=pV0[1]-pV1[1]; 
     pVRes[2]=pV0[2]-pV1[2]; 
    } 
} 
+1

Obliczenie wielkości siły wygląda prawidłowo. Nie wiem o wektorze. 'return fx, fy, fz;' nie zadziała. 'attraction' zwraca float, a nie 3. Gdzie zdefiniowano' vecLength' i dlaczego definiujesz 'av' o długości 4 zamiast 3? –

+0

Zmieniłem kod, ale problem nadal występuje. moja testowa planeta nie pojawia się na ekranie – user3476732

+0

mój błąd może leżeć gdzie indziej, ale tylko nie jestem pewien co do moich obliczeń dla kierunku – user3476732

Odpowiedz

6

Trudno wiedzieć bez danych wejściowych, ale myślę, że używasz do zmiennoprzecinkowej przelewem, ponieważ wartości obsługiwać ze są zbyt duże.

Na przykład, jeśli jednostki są w systemie jednostki SI, a następnie:

venus.mass = 4.87e+24; // kg 
earth.mass = 5.98e+24; // kg 

i licznik w równaniu staje:

self.mass * other.mass == 2.91047e+49; 

pojedynczej precyzji floating-point numbers nie może być większa niż 3.4E +38, więc produkt masowy traktowany jest jako nieskończoność.

Oczywiście wysokie wykładniki znoszą się wzajemnie, ponieważ odległości są również duże (rzędu 1e + 10), a stała grawitacyjna jest mała, ale jeśli powyższy produkt jest wynikiem działania, wszystkie wyniki zależne też są złe. (The -1.0#IND oznacza indefinte i odpowiada NaN, nie liczba, nieprawidłową liczbę zmiennoprzecinkową.)

Istnieje kilka sposobów, aby rozwiązać ten problem:

  • Wpisz wartości, które można do kwadratu bezpiecznie w reżimie zmiennoprzecinkowym. Na przykład, jeśli znormalizujesz masy z masą ziemi, otrzymasz liczby około 1,0, które powinny być bezpieczne do wykonywania obliczeń. Podobnie dobrą jednostką dla odległości może być astronomical unit.

  • Zmień ustawienie wyrażenia tak, aby nie nastąpiło przepełnienie wyrażeń pośrednich. Na przykład zamiast (m1 * m2)/(d*d) napisz (m1/d) * (m2/d).

  • Używaj zamiast pływaka. Maksymalna reprezentowalna wartość to double. 1,8e + 308. Zauważ, że ten problem nie zniknie z duoble, po prostu daje więcej miejsca na działanie. Na przykład powinieneś być dobry.