[OpenGL] Wywołanie funkcji raz

0

Cześć

Jest to mój pierwszy post na forum więc witam się. Uczę się C++ oraz OpenGL. Aktualnie rozpoznaje możliwość synchronizacji wyświetlania na przemian dwóch różnych tekstur na quadzie zgodnie ze zmianą wiersza granej muzyki. Muzyka jest w formacie trackerowym. W skrócie składa się z patternów, które w sobie zawierają wiersze. API playera trackerowego zwraca aktualnie grany wiersz. Potrzebuje, aby wraz ze zmianą wiersza muzyki o jeden wiersz była wyświetlana raz jedna raz druga tekstura (tekstury są wypełnione pixelam o różnych odcieniach danej barwy i wyświetlenie na przemian da efekty śnieżenia ekranu). W głównej pętli rysującej co ramkę pobierany jest aktualnie grany wiersz muzyki i przekazywany do funkcji rysującej tekstury na quadzie:

int posCurrVal = Music_GetPosition();
drawNoise(intPosCurrVal);

Kod funkcji wyświetlającej na przemian tekstury:

void drawNoise( int x )
{  
    glEnable( GL_TEXTURE_2D );
    glEnable( GL_DEPTH_TEST );
   
    if( x > prev )
    {
        glBindTexture( GL_TEXTURE_2D, texPosNoise );
        prev = x;
    }
    else
    {
        glBindTexture( GL_TEXTURE_2D, texNegNoise );
    }
   
    glBegin( GL_QUADS );
    glColor3f( 1.0f, 1.0f, 1.0f );
    glTexCoord2f( 0.0, 0.0 ); glVertex3f( - 15.0, - 15.0, 0.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f( - 15.0, 15.0, 0.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f( 15.0, 15.0, 0.0 );
    glTexCoord2f( 1.0, 0.0 ); glVertex3f( 15.0, - 15.0, 0.0 );
    glEnd();
   
    glDisable( GL_TEXTURE_2D );
    glDisable( GL_DEPTH_TEST );
}

Tekstury są bindowane na quada: raz jedna raz druga, ale ich wyświetlanie nie jest poprawne np. w danym momencie wyświetlane jest 1/3 jednej tekstury i 2/3 drugiej tekstury albo 1/2 jednej tekstury o 1/2 drugiej tekstury. Nie jest wyświetlana na zmianę raz jedna tekstura raz druga. Wyświetlanie zmienianej tekstury na quadzie jakby się "tnie". Dany wiersz muzyki jest grany przez krótki okres czasu i funkcja jest wywoływana wiele razy w tym czasie. Zależy mi na tym, aby funkcja byłą wywoływana tylko raz, dla danego wiersza muzyki. Czyli jak jest grany wiersz 1 wywoływana jest funkcja drawNoise(intPosCurrVal) raz, grany wiersz 1 wywoływana jest funkcja drawNoise(intPosCurrVal) raz, itd. Co muszę zmienić w kodzie? Potrzebuje jakiejś zmiennej logicznej?

Pozdrawiam

0
int posCurrVal = Music_GetPosition();

Może lepiej int musicPos albo podobnie? "CurrVal" nie wnosi praktycznie żadnej informacji.

void drawNoise( int x )

Tu to samo, jakiś x, za miesiąc zapomnisz co ten x miał znaczyć.

    if( x > prev )

Wystarczy if (x % 2 == 0) i nie musisz zapamiętywać żadnego prev.

Co muszę zmienić w kodzie?

Za mało pokazałeś. Właściwie zupełnie nie to co powinieneś...
Kiedy jest rysowana scena? W pętli cały czas, czy na żądanie? Z opisu wynika że chciałbyś rysować tylko na żądanie.
Czego właściwie używasz do obsługi okna? Jakiś GLUT, WinAPI, coś innego - nic nie wiadomo…
Czy masz podwójne buforowanie czy nie masz itp.....

Generalnie większość przykładów do OpenGL-a w necie dotyczy rysowania w pętli czasu rzeczywistego, czyli w kółko, jak w grach. I z tego co mi wiadomo to jedyny sposób obsługiwany przez GLUTa.
Rysować w OpenGL statycznie (czyli raz i już) oczywiście można, ale np. w WinAPI, i też trzeba wiedzieć jak to zrobić dobrze.

0

Dzięki za sugestie zmiany nazw zmiennych, pozmieniam je. Scena jest rysowana cały czas w pętli rysującej. Jak się zmieni grany wiersz muzyki, chciałbym wywołać tylko raz funkcję drawNoise(). Do obsługi okna wykorzystuje WinAPI. Nie mam podwójnego buforowania. Jakie kawałki kodu pokazać jeszcze?

0

Zauważ sprzeczność w tym co mówisz: z jednej strony mówisz że rysujesz przez cały czas (co oznacza odrysowywanie całego okna, bo zapewne jest tam glClear), a z drugiej strony chciałbyś coś rysować „tylko raz” tzn. tylko czasami?

Tak to nie ma. Albo raz, albo w kółko.

0

Może nie jasno napisałem, oto doprecyzowanie:) W głównej funkcji rysującej DrawGLScene() funkcja drawNoise() jest wywoływana w każdej iteracji. Jeden wiersz muzyki trwa 0,09 sekundy w związku z tym
zmienna intPosCurrVal ma jedną wartość przez te 0,09 sekundy. Dalej w związku z tym funkcja drawNoise() jest wywoływana przez okres 0,09 sekundy dla tej samej wartości zmiennej intPosCurrVal. Wartość zmiennej intPosCurrVal zwiększa się o jeden, gdy będzie grany następny wiersz muzyki. Chciałbym wywoływać fukncję drawNoise() tylko raz dla danej wartości zmiennj intPosCurrVal. Jak wartość tej zmiennej zmieni się o jeden to chciabym jeden raz wywołać raz funkcję drawNoise() dla zmienionej wartości zmiennej intPosCurrVal itd. Innymi słowami w głównej funkcji rysującej, która jest wywoływana cały czas chciałbym wywołać tylko raz funkcję drawNoise() jak wartość zmiennej intPosCurrVal zwięszky się o 1.

int DrawGLScene(GLvoid)						
{
	int posCurrVal = Music_GetPosition();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

	drawNoise(intPosCurrVal);
	// pozostały kod

	glFlush();
	return TRUE;	
}

Jak coś jest niejasne to z chęcią wyjaśnię:)

0

Ktuś cuś wie?

1

funkcja drawNoise() jest wywoływana w każdej iteracji

chciabym jeden raz wywołać raz funkcję drawNoise() dla zmienionej wartości zmiennej intPosCurrVal

Nadal nie widzisz tu sprzeczności?
Skoro w każdej iteracji robisz glClear (na dodatek źle, bo najpierw czyścisz a potem ustawiasz kolor czyszczenia, no ale od drugiej klatki począwszy to zacznie działać i tak) to robienie drawNoise rzadziej niż rysowanie całej sceny jest bezcelowe (jakikolwiek efekt drawNoise'a zostanie zamazany najbliższym Clearem).

Pytanie czy rzeczywiście potrzebujesz renderować całą scenę bez przerwy, a jeżeli tak (bo zmienia się coś innego na ekranie poza drawNoise) to pytanie drugie dlaczego chcesz unikać wykonywania drawNoise w każdej iteracji.

0

Wychodzi na to, że nie wyjaśniłem do końca jasno:) W obecnym kodzie funkcja drawNoise() jest wywoływana w każdej iteracji dla każdej wartości zmiennej intPosCurrVal. Zależy mi, aby tak zmodyfikować kod w taki sposób, aby jeden raz wywołać funkcję drawNoise() dla zmienionej wartości zmiennej intPosCurrVal. Moim celem jest wyświetlanie na przemian dwóch różnych tekstur na quadzie zgodnie ze zmianą wiersza granej muzyki. Jeżeli można zastosować jakieś inne podejście od mojego (może błędnego) proszę o jakieś sugestie.

0

W obecnym kodzie funkcja drawNoise() jest wywoływana w każdej iteracji dla każdej wartości zmiennej intPosCurrVal.
Zależy mi, aby tak zmodyfikować kod w taki sposób, aby jeden raz wywołać funkcję drawNoise() dla zmienionej wartości zmiennej intPosCurrVal.

Tak, ja to rozumiem, bo mówisz to po raz kolejny.
Czego nie rozumiem to w czym widzisz problem...

int posCurrVal = Music_GetPosition();
if (posCurrVal!= posOldVal)
{
    drawNoise(posCurrVal);
    posOldVal = posCurrVal;
}
0

Dzięki za sugestie. Moje podejście było błędne. Zastosowałem następujące rozwiązanie: w każdej ramce pobieram wartość zwracanego wiersza granej muzyki, robię dzielenie z resztą i ustawiam wartość logiczną, a na jej podstawie ustawiam właściwą teksturę (każda tekstura ma noisowy charakter) quada w dalszej funkcji. Też działa dobrze.

if(( intPosCurrVal % 4 == 0 ) || (intPosCurrVal % 4 == 1))
{
    changeNoiseTexture = true;
}
else
{
    changeNoiseTexture = false;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1