OpenGL niezależny ruch.

0

Mam problem z programem w C z użyciem opengl. Nie chciałbym podawać kodu bez ostatecznej konieczności z lenistwa. Chodzi o to że jest to prosty sześcian. i chciwym żeby się poruszał ale robi to tylko po naciśnięciu jakiegoś guzika. Co należny zrobić? Cos ja timer? Ma ktoś jakaś rade? program jest w C.

0

Wrzuć logikę w główną pętlę.

0

Trochę zależy od tego jak GL inicjalizujesz (używasz GLUT np.?).

Ogólny pomysł jest taki że (pseudokod):

void on_key_down() {
    moving = true;  // reakcja na naciśnięcie klawisza, cube zaczyna sie ruszać
}

void on_key_up() {
    moving = false; // reakcja na podniesienie klawisza, cube przestaje sie ruszać
}

void main_loop() { // pętla główna, gdzieś ją pewnie już masz w programie, chyba że np. używasz GLUT który robi to za Ciebie
    while (true) {
        if (moving) {
            cube_position += step; // ściśle to bardziej velocity / deltatime
         }
         draw_cube(); // i rysuje na pozycji cube_position
    }
}
0

Właściwie to trochę źle to napisałem. Do funkcji Wyrysowującej wprowadzam zwiększanie wartości zmiennej globalnej rotacyjnej. Sześcian sie nie porusza, robi to tylko kiedy trzyma się okienko i porusza szczególnie poza krawędziami obrazu monitora. Nie wiem jak temu zaradzić z biblioteka opengl. Nie używam glut , tam chyba jest specjalna funkcja obsługująca funkcje wyświetlającą. Wprowadzane jest odczytywanie klawiszy jak up i jakby czekało albo nie przechodziło do kolejnej linijki w pewnym miejscu i odświeżało aktualny obraz.

0

Brzmi to trochę tak jakbyś nie wywoływał sam wyrysowowywania w pętli (kiedy porusza się oknem za krawędziami ekranu okno dostaje WM_PAINT). Skoro zmieniasz pozycje co każde wyrysowanie, a pozycja zmienia się tylko kiedy ruszasz oknem, to znaczy że rysowanie nie jest wykonywane bez przerwy.

PS. Jeśli nie to, daj odpowiedzialny fragment kodu, bo tak to można zgadywać.

1

Musiałbyś pokazać trochę kodu.

Pod Windows komunikat WM_PAINT ma jakby dwa tryby:

  • jeśli (pośrednio lub bezpośrednio) wywołujesz ValidateRect(), to Windows będzie odrysowywał okno tylko kiedy mu się zachce.
  • jeśli nie ma ValidateRect (ani BeginPaint/EndPaint) to okno będzie odrysowywane w kółko bez przerwy, zabierając 100% czasu procka ;-)

tobie pewnie chodzi o ten drugi wariant. można też robić InvalidateRect w jakimś timerze, by ograniczyć ilość klatek na sekundę.

0

#include "szescian.h"

LONG WINAPI WndProc( HWND, UINT, WPARAM, LPARAM );
HGLRC SetUpOpenGL( HWND hWnd );

// Wartosci poczatkowe
#define DEFAULT_Z_DIST 25
#define DEFAULT_PIVOT_VERT_ANGLE 0
#define DEFAULT_PIVOT_HORIZ_ANGLE 0
#define DEFAULT_PIVOT_X 0
#define DEFAULT_PIVOT_Y 0

float z_dist=DEFAULT_Z_DIST; // INSERT, PAGE UP
float pivot_vert_angle=DEFAULT_PIVOT_VERT_ANGLE; // UP, DOWN
float pivot_horiz_angle=DEFAULT_PIVOT_HORIZ_ANGLE; // LEFT, RIGHT
float pivot_x=DEFAULT_PIVOT_X; // DELETE, PAGE DOWN
float pivot_y=DEFAULT_PIVOT_Y; // HOME, END
double rot=0;

// ************ Deklaracje funkcji ************************

void DrawOpenGLScene( void ); // glowna funkcja rysujaca

// Skladowe funkcje obiektu graficznego

void szescian(void);

// ..............................

//******** Fukcje skladowe ********************************

void szescian(void)
{
rot++;
glRotatef(rot,1,0,0);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
{
// Parametry wierzcholkow

GLfloat sa[3]={0.0f,0.0f,0.0f};
GLfloat sb[3]={1.0f,0.0f,0.0f};
GLfloat sc[3]={1.0f,1.0f,0.0f};
GLfloat sd[3]={0.0f,1.0f,0.0f};
GLfloat se[3]={0.0f,0.0f,-1.0f};
GLfloat sf[3]={1.0f,0.0f,-1.0f};
GLfloat sg[3]={1.0f,1.0f,-1.0f};
GLfloat sh[3]={0.0f,1.0f,-1.0f};

// Sciany skladowe
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
	glVertex3fv(sa);
	glVertex3fv(sb);
	glVertex3fv(sc);
	glVertex3fv(sd);
glEnd();

	glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
	glVertex3fv(sb);
	glVertex3fv(sf);
	glVertex3fv(sg);
	glVertex3fv(sc);
glEnd();

glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_POLYGON);
	glVertex3fv(sf);
	glVertex3fv(se);
	glVertex3fv(sh);
	glVertex3fv(sg);
glEnd();

	glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
	glVertex3fv(se);
	glVertex3fv(sa);
	glVertex3fv(sd);
	glVertex3fv(sh);
glEnd();

	glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_POLYGON);
	glVertex3fv(sd);
	glVertex3fv(sc);
	glVertex3fv(sg);
	glVertex3fv(sh);
glEnd();

glColor3f(1.0f, 0.0f, 1.0f);
glBegin(GL_POLYGON);
	glVertex3fv(sa);
	glVertex3fv(sb);
	glVertex3fv(sf);
	glVertex3fv(se);
glEnd();
}

}

//********************************************************
// Glowna funkcja WINDOWS
//********************************************************

int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
static char szAppName[] = "OpenGL";
static char szTitle[]= "SZESCIAN"; // Nazwa okna
WNDCLASS wc; // zmienna klasy okna
MSG msg; // zmienna komunikatu
HWND hWnd; // uchwyt okna

// wypelnianie klasy okna 

wc.style         =
    CS_HREDRAW | CS_VREDRAW;// styl okna
wc.lpfnWndProc   = 
    (WNDPROC)WndProc;       // procedura okna
wc.cbClsExtra    = 0;       // dodatkowe dane
wc.cbWndExtra    = 0;       
wc.hInstance     =
    hInstance;              // instancja 
wc.hIcon         = NULL;    // nazwa ikony 
wc.hCursor       =
    LoadCursor(NULL, IDC_ARROW);// kursor
wc.hbrBackground = 
    (HBRUSH)(COLOR_WINDOW+1);// domyslny kolor okna
wc.lpszMenuName  = NULL;     
wc.lpszClassName =
    szAppName;               // nazwa klasy

// Rejestracja klasy okna

RegisterClass( &wc );

// Konstrukcja glownego okna 

hWnd = CreateWindow(
            szAppName, // app name
            szTitle,   // Text for window title bar
            WS_OVERLAPPEDWINDOW// Window style 
              // NEED THESE for OpenGL calls to work!
             | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
            NULL,     // no parent window
            NULL,     // Use the window class menu.
            hInstance,// This instance owns this window
            NULL      // We don't use any extra data
    );

// Jezeli okno nie zostanie utworzone, zwrot 0
if ( !hWnd )
    {
    return( 0 );
    }


ShowWindow( hWnd, nCmdShow );// Wyswietlanie okna
UpdateWindow( hWnd );        // Aktualizacja okna

// Uruchiomienie petli komunikatow
while (GetMessage(&msg, NULL, 0, 0)) 
{
    TranslateMessage( &msg ); // Przetwarzanie wiadomosci
    DispatchMessage( &msg );  // Zwolnienie wiadomosci
}

return( msg.wParam ); 

}

//********************************************************
// Procedura okna
//********************************************************

LONG WINAPI WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
HDC hDC;

static HGLRC hRC; // Note this is STATIC!

PAINTSTRUCT ps;

GLdouble gldAspect;

GLsizei glnWidth, glnHeight;

float change;


// Petla komunikatow 

switch (msg)
  {
   case WM_CREATE:
       hRC = SetUpOpenGL( hWnd );	// Inicjalizacja OpenGL
       return 0;

   case WM_SIZE:
        hDC = GetDC (hWnd);			// Kontekst urzadzenia
        wglMakeCurrent (hDC, hRC);
    
        // Usawienie rozmiarow okna graficznego
        
		glnWidth = (GLsizei) LOWORD (lParam);
        glnHeight = (GLsizei) HIWORD (lParam);
        
		// Aspekt DC
		gldAspect = (GLdouble)glnWidth/(GLdouble)glnHeight;
   
        glMatrixMode( GL_PROJECTION );// Ustawienie macierzy projekcji
        
		glLoadIdentity();
        
		// Rodzaj transformacji ekranowej
        gluPerspective(
            30.0,      // kat 
            gldAspect, // aspekt
            1.0,       // polozenie plaszczyzny blizszej
            1000.0 );  // polozenie plaszczyzny dalszej

        glViewport( 0, 0, glnWidth, glnHeight );
        
		// czyszczenie
		glClearColor(0.5f,0.5f,0.5f,1.0f);
		
		glEnable(GL_COLOR_MATERIAL);
		wglMakeCurrent( NULL, NULL );
        ReleaseDC( hWnd, hDC );
        return 0;

    case WM_PAINT:
        // rysowanie sceny

        hDC = BeginPaint( hWnd, &ps );
        wglMakeCurrent( hDC, hRC );
        
        DrawOpenGLScene();
		
		SwapBuffers(hDC);
        
        wglMakeCurrent( NULL, NULL );

        EndPaint( hWnd, &ps );
        return 0;       
        
    case WM_DESTROY:
        // zamykanie 
        wglDeleteContext( hRC );
        PostQuitMessage( 0 );
        return 0;

	case WM_KEYDOWN: //************ OBSLUGA KLAWISZY ***********************
		if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
			change=1.0f;
		else
			change=0.1f;

		switch ((int)wParam)
		{
			// obrot w pionie
			case VK_UP:
				pivot_vert_angle+=5;
				if (pivot_vert_angle>=360)
					pivot_vert_angle-=360;
				InvalidateRect(hWnd, NULL, FALSE);
				break;
			case VK_DOWN:
				pivot_vert_angle-=5;
				if (pivot_vert_angle<0)
					pivot_vert_angle+=360;
				InvalidateRect(hWnd, NULL, FALSE);
				break;

			// obrot w poziomie
			case VK_RIGHT:
				pivot_horiz_angle+=5;
				if (pivot_horiz_angle>=360)
					pivot_horiz_angle-=360;
				InvalidateRect(hWnd, NULL, FALSE);
				break;
			case VK_LEFT:
				pivot_horiz_angle-=5;
				if (pivot_horiz_angle<0)
					pivot_horiz_angle+=360;
				InvalidateRect(hWnd, NULL, FALSE);
				break;

			// przesuniecia w poziomie
			case VK_NEXT:
				if ((pivot_x+change)<400)
					pivot_x+=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;
			case VK_DELETE:
				if ((pivot_x-change)>-400)
					pivot_x-=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;

			// przesuniecia w pionie
			case VK_HOME:
				if ((pivot_y+change)<400)
					pivot_y+=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;
			case VK_END:
				if ((pivot_y-change)>-400)
					pivot_y-=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;

			// odleglosc
			case VK_INSERT:
				if ((z_dist+change)<600)
					z_dist+=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;
			case VK_PRIOR:
				if ((z_dist-change)>1)
					z_dist-=change;
				InvalidateRect(hWnd, NULL, FALSE);
				break;

			// wyjscie z programu
			case VK_ESCAPE:
				PostMessage(hWnd, WM_CLOSE, 0, 0);
				return 0;
		}
    }


return DefWindowProc( hWnd, msg, wParam, lParam );

}

//*******************************************************
// Uruchomienie OpenGL w srodowisku Windows wymaga
// wlaczenie trybu pikselowego oraz ustawienia
// kontekstu renderowania
//*******************************************************

HGLRC SetUpOpenGL( HWND hWnd )
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof (PIXELFORMATDESCRIPTOR), // rozmiar struktury
1, // numer wersji
PFD_DRAW_TO_WINDOW | // flaga rysowania w oknie,
PFD_SUPPORT_OPENGL | // uzycie OpenGL
PFD_DOUBLEBUFFER, // uzycie podwojnego buforowania
PFD_TYPE_RGBA, // model kolorow - RGBA
24, // kolor 24-bitowy
0, 0, 0,
0, 0, 0, // trezerwa
0, 0, // brak bufora alpha
0, 0, 0, 0, 0, // brak bufora akumulacji
32, // bufor glebokosci 32-bitowy
0, // brak bufora szablonu
0, // brak bufora pomocniczego
PFD_MAIN_PLANE, // warstwa
0, // rezerwa - 0
0, // maska
0, // maska widoczna
0 // maska bledow
};

// zmienne
int nMyPixelFormatID;

HDC hDC;

HGLRC hRC;

hDC = GetDC( hWnd );

// Inicjalizacja trybu pikselowego 

nMyPixelFormatID = ChoosePixelFormat( hDC, &pfd );
SetPixelFormat( hDC, nMyPixelFormatID, &pfd );

// Inicjalizacja kontekstu renderowania

hRC = wglCreateContext( hDC );
ReleaseDC( hWnd, hDC );

return hRC;

}

//********************************************************
// Glowna funkcja rysujaca.
//********************************************************

void DrawOpenGLScene( )
{
GLfloat position[4]={10.0f, 10.0, 100.0f, 0.0f};

// flagi czynnosci pomocniczych

glEnable( GL_DEPTH_TEST );

// czyszczenie buforow
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

//glEnable(GL_CULL_FACE);
glEnable(GL_COLOR_MATERIAL);

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);

// wlaczenie oswietlenia
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);


// transformacja obserwacji

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

// umiejscowienie kamery w odleglym miejscu
glTranslatef( pivot_x, pivot_y, -z_dist );
glRotatef(pivot_vert_angle, 1, 0, 0);
glRotatef(pivot_horiz_angle, 0, 1, 0);

glPushMatrix();
	//szescian !!!!!!!!!!!!!!!!!!!!!!!!!!
	szescian();
glPopMatrix();

glFlush ();

}

0

wc.style =
CS_HREDRAW | CS_VREDRAW;// styl okna

Brakuje CS_OWNDC.

case WM_SIZE:
hDC = GetDC (hWnd); // Kontekst urzadzenia
wglMakeCurrent (hDC, hRC);
...
wglMakeCurrent( NULL, NULL );
ReleaseDC( hWnd, hDC );
return 0;

Wywal GetDC, wglMakeCurrent i ReleaseDC.

case WM_PAINT:
// rysowanie sceny

         hDC = BeginPaint( hWnd, &ps );
         wglMakeCurrent( hDC, hRC );
         
         DrawOpenGLScene();
         
         SwapBuffers(hDC);
         
         wglMakeCurrent( NULL, NULL );

         EndPaint( hWnd, &ps );
         return 0;

Wywal BeginPaint, wglMakeCurrent i EndPaint.

Usunięcie EndPaint spowoduje odrysowywanie okna bez przerwy. Możesz więc wywalić wszystkie InvalidateRect.

// NEED THESE for OpenGL calls to work!
| WS_CLIPCHILDREN | WS_CLIPSIBLINGS,

Nieprawda. Do OpenGL-a potrzebne jest CS_OWNDC, a nie WS_CLIPCHILDREN ani WS_CLIPSIBLINGS.

0

Wybacz troche sie zgubiłem w twojej wypowiedzi, Starałem się robic zgodnie z nia ale nadal sześcian nie porusza sie i nie odzweza sie obraz na bieżąco ze zmianami. Może jeszcze jakaś pomoc, bylbym wdzieczny. Brakuje CS_OWNDC skad wziac ?

0

Brakuje CS_OWNDC skad wziac ?

Trzeba, niestety, samodzielnie paluszkami wpisać.
Albo nie, czekaj, napiszę dla ciebie, tylko sobie skopiuj i wklej tam gdzie trzeba.

CS_OWNDC
0

Gdybym mógł prosić o wklejenie ewentualnie kodu w odp. Byłbym wdzięczny.

0

wc.style =
CS_HREDRAW | CS_VREDRAW;// styl okna

Brakuje CS_OWNDC.

    wc.style         =
         CS_HREDRAW | CS_VREDRAW | CS_OWNDC;// styl okna
0
Azarien napisał(a):

Wywal BeginPaint, wglMakeCurrent i EndPaint.

Usunięcie EndPaint spowoduje odrysowywanie okna bez przerwy. Możesz więc wywalić wszystkie InvalidateRect.

Tak się tego nie robi.
Animacje, albo jakieś gry, rysują bez przerwy w głównej pętli gdy nie ma komunikatów, albo i zawsze.

if( PeekMessage(... ) ) obsługa;
// else
rysujemy;

A w wm_paint nic nie robimy, czyli tak:

BeginPaint...
// tu można rysować ale po co, skoro to i tak ciągle się rysuje w mainloop.
EndPain();

Azarien napisał(a):

Nieprawda. Do OpenGL-a potrzebne jest CS_OWNDC, a nie WS_CLIPCHILDREN ani WS_CLIPSIBLINGS.

Chyba głupoty.
Rysujesz poprzez ten hglrc, a nie po tym hdc...

0

Do prostych rysowanek można użyć WM_TIMER,
i tam przesuwać sobie i rysować te obrazki (ewentualnie invalidateRect, a potem rysować normalnie, tj. w wm_paint).

0

https://www.opengl.org/wiki/Platform_specifics:_Windows "Be sure to use the CS_OWNDC flag.". Miałem przynajmniej jeden komputer, na którym TRZEBA było podać CS_OWNDC. Nie widzę powodu by się upierać przeciwnie. - Azarien dzisiaj, 10:30

To weź examples do C++ w VS i tam jest przykładu użycia opengl z MFC - cube, i znajdź tam CS_OWNDC.

Może błąd polega na czymś innym.
Np. nie musisz używać wglMakeCurrent za każdym razem, gdy rysujemy w wm_paint, bo wystarczy raz to zrobić;
ale to i tak nawali, gdy mamy kilka okien w których rysujemy za pomocą opengl.

Podobno też niektóre dawniejsze drivery opengl były zjeb*** i wtedy to cs_owndc pomagało.

Można sobie oczywiście używać spokojnie owndc - na pewno nie zaszkodzi, a i usuwać tego dc wtedy nie potrzeba.
Kiedyś były ostro limitowane zasoby - w win 98 i starszych, więc sobie tworzyli takie głupoty.
A może dzisiaj jest już stale trzymane to dc dla każdego okna, pomijając te standardowe contros - static, button, ect., bo to byłaby lekka przesada...

0

Ok działa coś tam wykliniłem, ale mam jeszcze inne pytanie. Nie używam glut a chciałbym stworzyć kule, jednak mam trudności z tym. Próbowałem po sworzniu dysku tak go zmodyfikować aby było ok ale mimo wielu prób wychodzą mi jakieś straszaki. Poradzi ktoś?

0

Nie używam glut a chciałbym stworzyć kule

użyj gluSphere().

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