Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Silnik Graficzny z wykorzystaniem matematyki niższej - czyli jak ominąć macierze

Ostatnio zmodyfikowano 2023-09-10 15:40
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[C++] Silnik Graficzny z wykorzystaniem matematyki niższej - czyli jak ominąć macierze
» 2023-07-29 19:01:24
 Prosto, krótko i na temat.  
Wymyśliłem funkcje na rotacje (x), (y), (z).
Potrzebuje rotacji (x,y,z)..
Korzystałem z algorytmu rysowania zegara analogowego.

Rotacja miała działac nastepujaca:
-pobierz obecny kat nachylenia wierzchołka do centrum modelu
-oblicz długość odcinka od wierzcholka do centrum modelu
-dodaj wektor rotacji do wierzholka z użyciem funkcji trygonometrycznych dla sumy kątów ( obecny kat + nowy kat)


Rotacje działają pojedynczo ale "razem" nie działają (Jak ustawiasz kat tylko dla jednej osi a pozostałe rotacje "zakomentujesz" algorytm działa), zanikają lub niweluja się. Mój zbyt prosty umysł nie potrafi tego przetworzyc.

Zalozenia
1. os Z rośnie od ekranu wgląb, os Y rośnie w górę, os X rośnie w prawo. Punkt 0 dla wszystkich osi to centrum ekranu.
2. Delta Z (dz) to stała 2.f do "stymulowanie 3D" x=x+(z*/dz) ; y=y+(z/dx). Wtedy wydaje się jakby model był pod kątem przechylony pod kątem 45stopni w osi X i 45stopni wokół osi y. (osobiście nazywam to rzutem "3 do 2D")
3. V - vertice, R - rotate vertice, P - projected vertice
 
Oto mój kod

C/C++
class trit
{
public:
   
float v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z; // vertexes (the fastest than class vector3)
   
float r, g, b, a; // colors: red green blue
   
trit * next;
   
   
float r1x, r1y, r1z, r2x, r2y, r2z, r3x, r3y, r3z; // rotated vertexes
   
float p1x, p1y, p2x, p2y, p3x, p3y; // projection
   
float cx, cy, cz; // used to sorting
   
trit( float, float, float, float, float, float, float, float, float, float, float, float, float );
   
trit( trit * );
   
~trit();
};

Triangle * t = New triangle(
-
100, - 50, 0,
100, - 50, 0,
0, 50, 0 );
float toDegrees = 180.f / M_PI;
float toRads = M_PI / 180.f;
float dz = 2.f; // delta z

float deg1z, deg2z, deg3z; // angle in degrees
float deg1y, deg2y, deg3y;
float deg1x, deg2x, deg3x;

float len1, len2, len3; // dlugosc odcinka miedzy centerModel a verticeOfModel

float fullAnglez1, fullAnglez2, fullAnglez3; // ( current angle + addedAngle ) w radianach
float fullAngley1, fullAngley2, fullAngley3;
float fullAnglex1, fullAnglex2, fullAnglex3;

// ROTATE Z ( adding vector of movement z )
deg1z = atan2( cy - t->v1y, cx - t->v1x ) * toDegrees;
deg2z = atan2( cy - t->v2y, cx - t->v2x ) * toDegrees;
deg3z = atan2( cy - t->v3y, cx - t->v3x ) * toDegrees;

fullAnglez1 =( deg1z + anglez ) * toRads;
fullAnglez2 =( deg2z + anglez ) * toRads;
fullAnglez3 =( deg3z + anglez ) * toRads;

len1 = sqrt( pow( cx - t->v1x, 2 ) + pow( cy - t->v1y, 2 ) + pow( cz - t->v1z, 2 ) );
len2 = sqrt( pow( cx - t->v2x, 2 ) + pow( cy - t->v2y, 2 ) + pow( cz - t->v2z, 2 ) );
len3 = sqrt( pow( cx - t->v3x, 2 ) + pow( cy - t->v3y, 2 ) + pow( cz - t->v3z, 2 ) );

t->r1x = cx + len1 * sin( fullAnglez1 );
t->r1y = cy + len1 * cos( fullAnglez1 );
t->r1z = t->v1z;

t->r2x = cx + len2 * sin( fullAnglez2 );
t->r2y = cy + len2 * cos( fullAnglez2 );
t->r2z = t->v2z;

t->r3x = cx + len3 * sin( fullAnglez3 );
t->r3y = cy + len3 * cos( fullAnglez3 );
t->r3z = t->v3z;
// TU JUZ NIE DZIALA
// ROTATE Y ( adding vector of movement y )
deg1y = atan2( cz - t->v1z, cx - t->v1x ) * toDegrees;
deg2y = atan2( cz - t->v2z, cx - t->v2x ) * toDegrees;
deg3y = atan2( cz - t->v3z, cx - t->v3x ) * toDegrees;

fullAngley1 =( deg1y + angley ) * toRads;
fullAngley2 =( deg2y + angley ) * toRads;
fullAngley3 =( deg3y + angley ) * toRads;

len1 = sqrt( pow( cx - t->v1x, 2 ) + pow( cy - t->v1y, 2 ) + pow( cz - t->v1z, 2 ) );
len2 = sqrt( pow( cx - t->v2x, 2 ) + pow( cy - t->v2y, 2 ) + pow( cz - t->v2z, 2 ) );
len3 = sqrt( pow( cx - t->v3x, 2 ) + pow( cy - t->v3y, 2 ) + pow( cz - t->v3z, 2 ) );

t->r1x = t->r1x - len1 * cos( fullAngley1 );
t->r1y = t->r1y;
t->r1z = t->r1z + len1 * sin( fullAngley1 );

t->r2x = t->r2x - len2 * cos( fullAngley2 );
t->r2y = t->r2y;
t->r2z = t->r2z + len2 * sin( fullAngley2 );

t->r3x = t->r3x - len3 * cos( fullAngley3 );
t->r3y = t->r3y;
t->r3z = t->r3z + len3 * sin( fullAngley3 );


// ROTATE X ( adding vector of movement x )
deg1x = atan2( cy - t->r1y, cz - t->r1z ) * toDegrees;
deg2x = atan2( cy - t->r2y, cz - t->r2z ) * toDegrees;
deg3x = atan2( cy - t->r3y, cz - t->r3z ) * toDegrees;

fullAnglex1 =( deg1x + anglex ) * toRads;
fullAnglex2 =( deg2x + anglex ) * toRads;
fullAnglex3 =( deg3x + anglex ) * toRads;

len1 = sqrt( pow( cx - t->r1x, 2 ) + pow( cy - t->r1y, 2 ) + pow( cz - t->r1z, 2 ) );
len2 = sqrt( pow( cx - t->r2x, 2 ) + pow( cy - t->r2y, 2 ) + pow( cz - t->r2z, 2 ) );
len3 = sqrt( pow( cx - t->r3x, 2 ) + pow( cy - t->r3y, 2 ) + pow( cz - t->r3z, 2 ) );

t->r1x = t->r1x;
t->r1y = t->r1y + len1 * sin( fullAnglex1 );
t->r1z = t->r1z + len1 * cos( fullAnglex1 );

t->r2x = t->r2x;
t->r2y = t->r2y + len2 * sin( fullAnglex2 );
t->r2z = t->r2z + len2 * cos( fullAnglex2 );

t->r3x = t->r3x;
t->r3y = t->r3y + len3 * sin( fullAnglex3 );
t->r3z = t->r3z + len3 * cos( fullAnglex3 );

// POSITION OF TRIANGLE ( CENTER )
t->cx =( t->r1x + t->r2x + t->r3x ) / 3.f;
t->cy =( t->r1y + t->r2y + t->r3y ) / 3.f;
t->cz =( t->r1z + t->r2z + t->r3z ) / 3.f;

// PROJECTION 3D->2D
/*
   //  for tests the model ( czy dobre wspolrzedne obiektu podano - deltaZ )
   t->p1x = t->r1x + t->r1z/dz; t->p1y = t->r1y + t->r1z/dz;
   t->p2x = t->r2x + t->r2z/dz; t->p2y = t->r2y + t->r2z/dz;
   t->p3x = t->r3x + t->r3z/dz; t->p3y = t->r3y + t->r3z/dz;
  */


t->p1x = t->r1x; t->p1y = t->r1y;
t->p2x = t->r2x; t->p2y = t->r2y;
t->p3x = t->r3x; t->p3y = t->r3y;
P-180180
DejaVu
» 2023-07-29 19:30:46
Strzelałbym, że nie zapisujesz wyniku i... transformujesz oryginalne współrzędne, a nie po wykonaniu pierwszej rotacji. No ale mogę być w błędzie, bo kojarzę, że z 10+ lat temu miałem podobny problem :)
P-180181
tBane
Temat założony przez niniejszego użytkownika
» 2023-07-29 19:40:36
Done.
Ale nadal nie działa, algorytm metamorfozuje mój szesciokat jak w jakimś 4 wymiarze ..
Po rotacji dla osi z operuje na rotowanych już wierzcholkach i się psuje wszystko..

Nie wiem czy dobrze rozumuję, lecz myślę że może tu chodzić o to, że rotacja y względem rotacji z jest "przestawiona" o 90 stopni w osii.. Próbowałem dodawać i odejmować kąty dodatkowe (90 stopni) i nic to nie dało.

C/C++
for( trit * t = mesh; t != NULL; t = t->next )
{
   
   
// ROTATE Z ( adding vector of movement z )
    // pobranie katow obecnych dla wierzcholkow
   
deg1z = atan2( cy - t->v1y, cx - t->v1x ) * toDegrees;
   
deg2z = atan2( cy - t->v2y, cx - t->v2x ) * toDegrees;
   
deg3z = atan2( cy - t->v3y, cx - t->v3x ) * toDegrees;
   
// dodanie do tych katow wartosc rotacji
   
fullAnglez1 =( deg1z + anglez ) * toRads;
   
fullAnglez2 =( deg2z + anglez ) * toRads;
   
fullAnglez3 =( deg3z + anglez ) * toRads;
   
// obliczenoe dlugosci odcinkow od srodka modelu do wierzcholkow
   
len1 = sqrt( pow( cx - t->v1x, 2 ) + pow( cy - t->v1y, 2 ) + pow( cz - t->v1z, 2 ) );
   
len2 = sqrt( pow( cx - t->v2x, 2 ) + pow( cy - t->v2y, 2 ) + pow( cz - t->v2z, 2 ) );
   
len3 = sqrt( pow( cx - t->v3x, 2 ) + pow( cy - t->v3y, 2 ) + pow( cz - t->v3z, 2 ) );
   
// no i przeksztalcenia tzn.. przeksztalc "od punktu 0"  (jak na zegarze analogowym y=12:00, x=srodek=0 )
   
t->r1x = cx + len1 * sin( fullAnglez1 );
   
t->r1y = cy + len1 * cos( fullAnglez1 );
   
t->r1z = t->v1z;
   
   
t->r2x = cx + len2 * sin( fullAnglez2 );
   
t->r2y = cy + len2 * cos( fullAnglez2 );
   
t->r2z = t->v2z;
   
   
t->r3x = cx + len3 * sin( fullAnglez3 );
   
t->r3y = cy + len3 * cos( fullAnglez3 );
   
t->r3z = t->v3z;
   
   
// ROTATE Y ( adding vector of movement y )
   
deg1y = atan2( cz - t->r1z, cx - t->r1x ) * toDegrees;
   
deg2y = atan2( cz - t->r2z, cx - t->r2x ) * toDegrees;
   
deg3y = atan2( cz - t->r3z, cx - t->r3x ) * toDegrees;
   
   
fullAngley1 =( deg1y + angley ) * toRads;
   
fullAngley2 =( deg2y + angley ) * toRads;
   
fullAngley3 =( deg3y + angley ) * toRads;
   
   
len1 = sqrt( pow( cx - t->r1x, 2 ) + pow( cy - t->r1y, 2 ) + pow( cz - t->r1z, 2 ) );
   
len2 = sqrt( pow( cx - t->r2x, 2 ) + pow( cy - t->r2y, 2 ) + pow( cz - t->r2z, 2 ) );
   
len3 = sqrt( pow( cx - t->r3x, 2 ) + pow( cy - t->r3y, 2 ) + pow( cz - t->r3z, 2 ) );
   
   
t->r1x = t->r1x - len1 * cos( fullAngley1 );
   
t->r1y = t->r1y;
   
t->r1z = t->r1z + len1 * sin( fullAngley1 );
   
   
t->r2x = t->r2x - len2 * cos( fullAngley2 );
   
t->r2y = t->r2y;
   
t->r2z = t->r2z + len2 * sin( fullAngley2 );
   
   
t->r3x = t->r3x - len3 * cos( fullAngley3 );
   
t->r3y = t->r3y;
   
t->r3z = t->r3z + len3 * sin( fullAngley3 );
   
   
// ROTATE X ( adding vector of movement x )
   
deg1x = atan2( cy - t->r1y, cz - t->r1z ) * toDegrees;
   
deg2x = atan2( cy - t->r2y, cz - t->r2z ) * toDegrees;
   
deg3x = atan2( cy - t->r3y, cz - t->r3z ) * toDegrees;
   
   
fullAnglex1 =( deg1x + anglex ) * toRads;
   
fullAnglex2 =( deg2x + anglex ) * toRads;
   
fullAnglex3 =( deg3x + anglex ) * toRads;
   
   
len1 = sqrt( pow( cx - t->r1x, 2 ) + pow( cy - t->r1y, 2 ) + pow( cz - t->r1z, 2 ) );
   
len2 = sqrt( pow( cx - t->r2x, 2 ) + pow( cy - t->r2y, 2 ) + pow( cz - t->r2z, 2 ) );
   
len3 = sqrt( pow( cx - t->r3x, 2 ) + pow( cy - t->r3y, 2 ) + pow( cz - t->r3z, 2 ) );
   
   
t->r1x = t->r1x;
   
t->r1y = t->r1y + len1 * sin( fullAnglex1 );
   
t->r1z = t->r1z + len1 * cos( fullAnglex1 );
   
   
t->r2x = t->r2x;
   
t->r2y = t->r2y + len2 * sin( fullAnglex2 );
   
t->r2z = t->r2z + len2 * cos( fullAnglex2 );
   
   
t->r3x = t->r3x;
   
t->r3y = t->r3y + len3 * sin( fullAnglex3 );
   
t->r3z = t->r3z + len3 * cos( fullAnglex3 );
   
   
// POSITION OF TRIANGLE ( CENTER )
   
t->cx =( t->r1x + t->r2x + t->r3x ) / 3.f;
   
t->cy =( t->r1y + t->r2y + t->r3y ) / 3.f;
   
t->cz =( t->r1z + t->r2z + t->r3z ) / 3.f;
   
   
   
// PROJECTION 3D
   
t->p1x = t->r1x; t->p1y = t->r1y;
   
t->p2x = t->r2x; t->p2y = t->r2y;
   
t->p3x = t->r3x; t->p3y = t->r3y;
   
   
/*
  // PROJECTION 3D->2D ( procjection 3 to 2D ) ( for tests the model )
   t->p1x = t->r1x + t->r1z/dz; t->p1y = t->r1y + t->r1z/dz;
   t->p2x = t->r2x + t->r2z/dz; t->p2y = t->r2y + t->r2z/dz;
   t->p3x = t->r3x + t->r3z/dz; t->p3y = t->r3y + t->r3z/dz;
   */
   
}
P-180183
pekfos
» 2023-07-30 23:27:18
A czemu nie macierze? Skoro masz "zbyt prosty umysł", to najprościej byłoby skorzystać ze wzoru.
P-180187
tBane
Temat założony przez niniejszego użytkownika
» 2023-07-30 23:31:46
Bo chciałem "po swojemu" napisać :-) Kiedyś ktoś na tym forum uczył mnie jak za pomocą sin() i cos() rysować tarcze zegara analogowego i rotowac wskazówki :-) poszedłem o krok dalej.. I przypadkiem zaświtała mi w głowie 3-wymiarowa rotacja. Niby algorytm działa, ale tylko pojedynczo-choć ja uważam, że powinien działać. Nie wiem gdzie robię błąd i dlatego stoję w miejscu. A chcę napisać grę w której są aż 2 rotacje :D ( proszę. Tylko bez macierzy)
P-180188
pekfos
» 2023-07-30 23:44:16
Ale wiesz że macierz to tylko sposób na zwięzłe zapisanie współczynników do szeregu mnożeń i dodawań? Można by rozpisać mnożenie macierzy obrotu przez wektor, ale średnio widzę w tym sens. Twoje rozwiązanie już jest bardziej skomplikowane i używa cięższych operacji.
W twoim spaghetti w pierwszej kolejności bym patrzył czy w tej masie zmiennych nie ma błędów. Kod wygląda jak nakopiowany, więc nie zaktualizowanie zmiennej jest prawdopodobną pomyłką. Inna sprawa że nie powinieneś pisać tak kodu.
P-180189
tBane
Temat założony przez niniejszego użytkownika
» 2023-07-30 23:51:11
Dla mnie wydaje się czytelny. Widać kiedy zaczynają się obliczenia dla konkretnej rotacji. Dla każdej rotacji pobieramy kąt obecny, dodajemy do niego nowy kąt, ten kat wykorzystujemy w funkcji trygonometryczne, którą "skalujemy" odcinek cx-v1x, cx-v1x... cy-v1y.. etc.

To jest czytelne.

Dlaczego nie powinienem tak pisać kodu?
I czy widzisz tu jakiś błąd logiczny?
P-180192
pekfos
» 2023-07-31 00:04:45
To jest czytelne.
Dlaczego nie powinienem tak pisać kodu?
Może i jest czytelne. Dla ciebie, teraz. Czemu rotacje nie są wydzielone do funkcji? Powiedzmy 3 różnych, gdzie teraz są wszystkie wrzucone na kupę i kopiując kod trudziłeś się by każdy kod miał swoje unikalne zmienne, chociaż można było używać ponownie niektórych? Czemu wszystko jest rozbite na floaty, zamiast mieć strukturę z punktem? Nie ma różnicy w wydajności, co sugeruje twój komentarz, a znacznie upraszcza kod.
Twierdzisz że kod jest czytelny, ale nie możesz znaleźć w nim błędu. Teraz jakbym ja miał w nim szukać błędu, to muszę zaczynać od największych bzdur, jak nieaktualna nazwa zmiennej. Czytelny kod nie ma tylu bzdur do sprawdzania.
P-180194
« 1 » 2 3 4 5 6
  Strona 1 z 6 Następna strona