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

[OpenGL] Obrót ścian kostki Rubika - problem z mieszaniem się kolorów

Ostatnio zmodyfikowano 2016-01-07 16:34
Autor Wiadomość
veelenar
Temat założony przez niniejszego użytkownika
[OpenGL] Obrót ścian kostki Rubika - problem z mieszaniem się kolorów
» 2015-12-16 21:43:37
Hej, mam taki mały problem z opisaniem obrotów kostki Rubika, mianowicie mam funkcję(kod poniżej), która działa dla obrotu wokół jednej osi, lecz gdy w grę wejdzie więcej niż jedna oś - zaczyna się magia. To znaczy co drugi ruch źle wstawiane są kolory, np. zamiast niebieskiego robi się czarny, który jest wewnątrz kostki. Prosiłbym o sugestie co może być nie tak i co można zmienić, aby obroty działały poprawnie. Dzięki za każdą podpowiedź :)

C/C++
void ObrocMacierzSciany( osObrotu os, kierunekObrotu kierunek, int numerSciany )
{
    elementKostki macierz[ 3 ][ 3 ];
    elementKostki obracanaMacierz[ 3 ][ 3 ];
   
    switch( os ) {
    case x:
        for( int x = 0; x < 3; x++ )
        for( int y = 0; y < 3; y++ ) {
            macierz[ x ][ y ] = kostka[ numerSciany ][ x ][ y ];
        }
        break;
    case y:
        for( int x = 0; x < 3; x++ )
        for( int y = 0; y < 3; y++ ) {
            macierz[ x ][ y ] = kostka[ x ][ numerSciany ][ y ];
        }
        break;
    case z:
        for( int x = 0; x < 3; x++ )
        for( int y = 0; y < 3; y++ ) {
            macierz[ x ][ y ] = kostka[ x ][ y ][ numerSciany ];
        }
        break;
    }
   
    if( kierunek == lewo )
    //w lewo
    for( int i = 2; i >= 0; i-- )
    {
        for( int j = 0; j < 3; j++ )
        {
            obracanaMacierz[ j ][ 2 - i ] = macierz[ i ][ j ];
        }
    }
   
    if( kierunek == prawo )
    //w prawo
    for( int j = 2; j >= 0; j-- )
    {
        for( int i = 0; i < 3; i++ )
        {
            obracanaMacierz[ 2 - j ][ i ] = macierz[ i ][ j ];
        }
    }
   
    for( int i = 0; i < 3; i++ )
    for( int j = 0; j < 3; j++ ) {
        switch( os ) {
        case x:
           
            if( kierunek == lewo ) {
                obracanaMacierz[ i ][ j ].obrotx -= 1;
               
            }
            else if( kierunek == prawo ) {
                obracanaMacierz[ i ][ j ].obrotx += 1;
               
               
            }
            if( obracanaMacierz[ i ][ j ].obrotx < 0 )
                 obracanaMacierz[ i ][ j ].obrotx = 3;
           
            if( obracanaMacierz[ i ][ j ].obrotx > 3 )
                 obracanaMacierz[ i ][ j ].obrotx = 0;
           
           
            kostka[ numerSciany ][ i ][ j ] = obracanaMacierz[ i ][ j ];
           
           
            break;
           
        case y:
           
            if( kierunek == lewo )
            {
               
                obracanaMacierz[ i ][ j ].obroty -= 1;
               
            }
            else if( kierunek == prawo )
            {
               
                obracanaMacierz[ i ][ j ].obroty += 1;
               
            }
           
            if( obracanaMacierz[ i ][ j ].obroty < 0 )
                 obracanaMacierz[ i ][ j ].obroty = 3;
           
            if( obracanaMacierz[ i ][ j ].obroty > 3 )
                 obracanaMacierz[ i ][ j ].obroty = 0;
           
            kostka[ i ][ numerSciany ][ j ] = obracanaMacierz[ i ][ j ];
           
            break;
           
        case z:
            if( kierunek == lewo )
            {
               
                obracanaMacierz[ i ][ j ].obrotz -= 1;
            }
            else if( kierunek == prawo )
            {
               
                obracanaMacierz[ i ][ j ].obrotz += 1;
            }
           
            if( obracanaMacierz[ i ][ j ].obrotz < 0 )
                 obracanaMacierz[ i ][ j ].obrotz = 3;
           
            if( obracanaMacierz[ i ][ j ].obrotz > 3 )
                 obracanaMacierz[ i ][ j ].obrotz = 0;
           
            kostka[ i ][ j ][ numerSciany ] = obracanaMacierz[ i ][ j ];
           
           
            break;
        }
    }
}
P-142069
DejaVu
» 2015-12-21 16:47:20
Przypuszczam, że Twoim problemem jest fakt, że nie wykonujesz aktualizacji stanu kostki po wykonaniu obrotu. Zauważ, że skoro pierwsza iteracja działa, to po pierwszej iteracji powinieneś zapisać stan kostki obróconej i zresetować macierz obrotów. W kolejnej iteracji (czyli w kolejnym obrocie) wykonujesz ponownie tą samą operację względem 'aktualnego' stanu, a nie względem 'początkowego stanu kostki'.
P-142222
veelenar
Temat założony przez niniejszego użytkownika
» 2015-12-28 12:05:59
To może mieć sens, jednakże poprawiłem kolejność obrotów osi w funkcji wyświetlającej, teraz mam sytuację, że pierwsza seria obrotów (90 stopni w każdej płaszczyźnie) idzie zgodnie z założeniem, a następnie x i y się psują, a z idzie poprawnie. Nie wiem, czy faktycznie jest to problem, że po pierwszej serii obrotów powinienem zapisać stan kostki, czy jest to problem z czym innej, ale podejrzewam, że siedzi to w tej funkcji, lub w funkcji wyświetlania. Dzięki za podpowiedź, dam znać, czy rozwiązanie pomogło :)
P-142454
Gabes
» 2015-12-28 19:42:43
Czy nie powinieneś korzystać z tablicy trójwymiarowej?
Na Warsztat.GD widziałem jakiś czas temu projekt kostki może znajdziesz kontakt, jakąś konkretną pomoc.:)
P-142483
veelenar
Temat założony przez niniejszego użytkownika
» 2015-12-28 20:48:41
Ogólnie używam tablicy 3-wymiarowej. Te 2 wymiary to macierze pomocnicze, które mają za zadanie obrócić macierz wybranej ściany, a później ta macierz jest dopisywana do tablicy 3-wymiarowej w zależności czy jest to x, y czy z.
P-142492
veelenar
Temat założony przez niniejszego użytkownika
» 2016-01-06 14:11:39
Analizując indeksowania wpadłem na pomysł, że problemem mogłoby być złe skonstruowanie funkcji wyświetlania. Jeśli Wam to coś powie to wstawiam kod poniżej. Każda sugestia przebudowy jest jak najbardziej mile widziana :)

C/C++
void Display()
{
    // licznik czasu
    if( !frames++ )
         start_time = clock();
    // kolor tła - zawartość bufora koloru
    glClearColor( 0.3, 0.3, 0.3, 1.0 );
   
    // czyszczenie bufora koloru i głębi
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //czyści bufory
    // wybór macierzy modelowania
    glMatrixMode( GL_MODELVIEW );
   
    // włączenie testu bufora głębokości
    glEnable( GL_DEPTH_TEST );
   
    //glRotatef(kat, 0.0f, 1.0f, 0.0f);
    //glRotatef(kat, 0.0f, 0.0f, 1.0f);
    timer();
   
   
   
    for( int x = 0; x < 3; x++ ) {
        for( int y = 0; y < 3; y++ ) {
            for( int z = 0; z < 3; z++ ) {
                int * kolor = kostka[ x ][ y ][ z ].kolor;
               
                // macierz modelowania = macierz jednostkowa
                glLoadIdentity();
               
                // przesunięcie układu współrzędnych obiektu do środka bryły odcinania
                glTranslatef( 0, 0, -( neaar + faar ) / 2 );
               
                // skalowanie obiektu - klawisze "+" i "-"
                glScalef( scale, scale, scale );
               
                // obroty obiektu - prawa mysz
                glRotatef( rotatex, 1.0, 0, 0 );
                glRotatef( rotatey, 0, 1.0, 0 );
               
               
               
                if( os == osObrotu::x ) {
                    if( rotateWallDepth == x ) {
                        glRotatef( rotateWall, 1.0, 0, 0 );
                    }
                }
                else if( os == osObrotu::y )
                {
                    if( rotateWallDepth == y ) {
                        glRotatef( rotateWall, 0, 1.0, 0 );
                    }
                }
                else if( os == osObrotu::z )
                {
                    if( rotateWallDepth == z ) {
                        glRotatef( rotateWall, 0, 0, 1.0 );
                    }
                }
               
                glTranslatef( x * 0.6f - 0.6f,( y *- 0.6f ) + 0.6,( z *- 0.6f ) + 0.6f );
               
               
               
                glRotatef(( GLfloat )( 90.0f *( float )( kostka[ x ][ y ][ z ].obrotz ) ), 0, 0, 1.0f );
                glRotatef(( GLfloat )( 90.0f *( float )( kostka[ x ][ y ][ z ].obroty ) ), 0, 1.0f, 0 );
                glRotatef(( GLfloat )( 90.0f *( float )( kostka[ x ][ y ][ z ].obrotx ) ), 1.0f, 0, 0 );
               
               
                RysujSzescian( 0, 0, 0, kolor[ 0 ], kolor[ 1 ], kolor[ 2 ] );
            }
        }
    }
   
    //os = z;
    rotateWall += 0.05;
    if( rotateWall >= 90 ) {
        rotateWall = 0;
       
        if( os == osObrotu::z ) {
            ObrocMacierzSciany( os, lewo, rotateWallDepth );
        }
        else
        {
            ObrocMacierzSciany( os, prawo, rotateWallDepth );
        }
       
        rotateWallDepth++;
        if( rotateWallDepth > 2 )
             rotateWallDepth = 0;
       
       
        if( os == osObrotu::x )
             os = osObrotu::y;
        else if( os == osObrotu::y )
             os = osObrotu::z;
        else if( os == osObrotu::z )
             os = osObrotu::x;
       
        //LosujSciane();
    }
   
    glLoadIdentity();
   
    glTranslatef( 0, 0, - neaar );
    glColor3ub( 255, 255, 255 );
   
    // narysowanie napisu
    DrawString( - 12.5, 9.5, time_string );
   
    // skierowanie poleceń do wykonania
    glFlush();
   
    // zamiana buforów koloru
    glutSwapBuffers();
}

Dorzucam również kod funkcji generującej kostkę.

C/C++
void GenerujKostke() {
   
    for( int x = 0; x < 3; x++ ) {
        for( int y = 0; y < 3; y++ ) {
            for( int z = 0; z < 3; z++ ) {
                kostka[ x ][ y ][ z ].iloscScian = dwie;
                kostka[ x ][ y ][ z ].kolor[ 0 ] = 0;
                kostka[ x ][ y ][ z ].kolor[ 1 ] = 0;
                kostka[ x ][ y ][ z ].kolor[ 2 ] = 0;
                kostka[ z ][ y ][ x ].numerElementu = x + y + z;
                kostka[ x ][ y ][ z ].obrotx = 0;
                kostka[ x ][ y ][ z ].obroty = 0;
                kostka[ x ][ y ][ z ].obrotz = 0;
            }
        }
    }
   
    kostka[ 1 ][ 1 ][ 0 ].iloscScian = jedna;
    kostka[ 1 ][ 1 ][ 2 ].iloscScian = jedna;
    kostka[ 1 ][ 0 ][ 1 ].iloscScian = jedna;
    kostka[ 1 ][ 2 ][ 1 ].iloscScian = jedna;
    kostka[ 0 ][ 1 ][ 1 ].iloscScian = jedna;
    kostka[ 2 ][ 1 ][ 1 ].iloscScian = jedna;
   
    for( int i = 0; i < 3; i++ ) {
        for( int j = 0; j < 3; j++ ) {
            kostka[ 0 ][ i ][ j ].kolor[ 0 ] = 6;
            kostka[ 2 ][ i ][ j ].kolor[ 0 ] = 5;
            kostka[ i ][ 0 ][ j ].kolor[ 1 ] = 3;
            kostka[ i ][ 2 ][ j ].kolor[ 1 ] = 2;
            kostka[ i ][ j ][ 0 ].kolor[ 2 ] = 4;
            kostka[ i ][ j ][ 2 ].kolor[ 2 ] = 1;
           
            if(( i == 0 && j == 0 ) ||( i == 0 && j == 2 ) ||( i == 2 && j == 0 ) ||( i == 2 && j == 2 ) ) {
                kostka[ i ][ j ][ 0 ].iloscScian = trzy;
                kostka[ i ][ j ][ 2 ].iloscScian = trzy;
            }
        }
    }
P-142967
DejaVu
» 2016-01-07 16:34:41
Raczej trudno o ochotników szukających bugów w Twoim programie. Dostałeś wskazówki w czym może być problem i powinieneś spróbować samodzielnie drążyć dalej temat.
P-143070
« 1 »
  Strona 1 z 1