Podstawowy projekt OpenGL utworzony przy użyciu środowisk programistycznych firmy Microsoft.



Podobne dokumenty
Wprowadzenie do programowania w Windows

Laboratorium Grafiki Komputerowej i Animacji. Ćwiczenie I. Wprowadzenie do programowania w Windows

Procedura okna: LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

Informatyka I : Tworzenie projektu

IFiZR Laboratorium 5 Info

Komunikaty w Windows. Jarosław Kuchta

Programowanie w języku C++ z użyciem Windows API

Projektowanie i programowanie aplikacji biznesowych. Wykład 2

Podstawy programowania w języku C dla środowiska Windows

Dodanie nowej formy do projektu polega na:

Zegary. Zegary (timers) umożliwiają cykliczne w danych odstępach czasu wykonać określone operacje.

Politechnika Gdańska Katedra Optoelektroniki i Systemów Elektronicznych

Programowanie na poziomie sprzętu. Programowanie w Windows API

Podstawy programowania w języku C dla środowiska Windows

Tworzenie projektu asemblerowego dla środowiska Visual Studio 2008.

Visual Studio instalacja

WYKONANIE APLIKACJI OKIENKOWEJ OBLICZAJĄCEJ SUMĘ DWÓCH LICZB W ŚRODOWISKU PROGRAMISTYCZNYM. NetBeans. Wykonał: Jacek Ventzke informatyka sem.

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

I - Microsoft Visual Studio C++

PROE wykład 8 Interfejs użytkownika (GUI) dr inż. Jacek Naruniec

Podstawy technologii cyfrowej i komputerów

etrader Pekao Podręcznik użytkownika Strumieniowanie Excel

Instrukcja składania wniosku o dofinansowanie w systemie informatycznym IP na potrzeby konkursu nr 1/1.1.2/2015

Instrukcja laboratoryjna cz.3

1. Wstęp. 2. Szablon. 1 WinApi Wstęp i szablon. Czym jest API?

Rozpoczęcie pracy z programem.

Temat: Organizacja skoroszytów i arkuszy

Allegro5 część 1 - Witaj Świecie! Projekt, inicjalizacja, tworzenie okna, czcionki. Autor: Kamil Krzyszczuk - C mons

Karty pracy. Ustawienia. W tym rozdziale została opisana konfiguracja modułu CRM Karty pracy oraz widoki i funkcje w nim dostępne.

1. Wprowadzenie. 1.1 Uruchamianie AutoCAD-a Ustawienia wprowadzające. Auto CAD Aby uruchomić AutoCada 14 kliknij ikonę

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Expo Composer Garncarska Szczecin tel.: info@doittechnology.pl. Dokumentacja użytkownika

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Utworzenie aplikacji mobilnej Po uruchomieniu Visual Studio pokazuje się ekran powitalny. Po lewej stronie odnośniki do otworzenia lub stworzenia

Arkusz strona zawierająca informacje. Dokumenty Excela są jakby skoroszytami podzielonymi na pojedyncze arkusze.

Programowanie niskopoziomowe

Programowanie. Ćwiczenie Język C. Środowisko programowania Visual Studio

Programowanie obiektowe

Instrukcja użytkownika

Instrukcja importu dokumentów z programu Fakt do programu Płatnik

Wprowadzenie do środowiska Qt Creator

Baltie 3. Podręcznik do nauki programowania dla klas I III gimnazjum. Tadeusz Sołtys, Bohumír Soukup

FAQ: /PL Data: 3/07/2013 Konfiguracja współpracy programów PC Access i Microsoft Excel ze sterownikiem S7-1200

1. Wybierz polecenie rysowania linii, np. poprzez kliknięcie ikony W wierszu poleceń pojawi się pytanie o punkt początkowy rysowanej linii:

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

I. Spis treści I. Spis treści... 2 II. Kreator szablonów Tworzenie szablonu Menu... 4 a. Opis ikon Dodanie nowego elementu...

Edytor tekstu OpenOffice Writer Podstawy

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Galileo v10 pierwszy program

Podręcznik użytkownika programu. Ceremonia 3.1

Tworzenie prezentacji w MS PowerPoint

Minimalna wspierana wersja systemu Android to zalecana 4.0. Ta dokumentacja została wykonana na telefonie HUAWEI ASCEND P7 z Android 4.

Ćwiczenia laboratoryjne. Oprogramowanie i badanie prostych metod sortowania w tablicach

Programowanie obiektowe zastosowanie języka Java SE

Certyfikat niekwalifikowany zaufany Certum Silver. Instalacja i użytkowanie pod Windows Vista. wersja 1.0 UNIZETO TECHNOLOGIES SA

1. Przypisy, indeks i spisy.

1.3. Tworzenie obiektów 3D. Rysunek 1.2. Dostępne opcje podręcznego menu dla zaznaczonego obiektu

Nowe funkcjonalności wersji

4.Arkusz kalkulacyjny Calc

Projekt procesora NIOSII w strukturze programowalnego układu logicznego CYCLONEII EP2C35F672C6 podłączenie i obsługa wyświetlacza LCD.

Microsoft.NET: ASP.NET MVC + Entity Framework (Code First)

Celem ćwiczenia jest zapoznanie się z podstawowymi funkcjami i pojęciami związanymi ze środowiskiem AutoCAD 2012 w polskiej wersji językowej.

Podstawy WINDOWS 9x, 2000, XP

Rys.1. Technika zestawiania części za pomocą polecenia WSTAWIAJĄCE (insert)

Laboratorium 1. Programowanie II - Kierunek Informatyka. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej

1 Podstawy c++ w pigułce.

Symfonia Produkcja Instrukcja instalacji. Wersja 2013

ActionFX oprogramowanie do sterowania efektami platform i kin 7D V1.0.1

Fragment tekstu zakończony twardym enterem, traktowany przez edytor tekstu jako jedna nierozerwalna całość.

Programowanie współbieżne. Tworzenie i obsługa semaforów oraz wątków przy użyciu funkcji Windows API.

Wprowadzenie do biblioteki klas C++

Microsoft Visual C : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop Spis treści

Dokument zawiera podstawowe informacje o użytkowaniu komputera oraz korzystaniu z Internetu.

Instalowanie dodatku Message Broadcasting

SimplySign logowanie i rejestracja na komputerze oraz dodanie certyfikatu do programu Płatnik

System Informatyczny CELAB. Terminy, alarmy

Microsoft Visual C++

Instrukcja dotycząca konwersji dokumentów LaTeX do plików w formacie RTF

Politechnika Poznańska Wydział Budowy Maszyn i Zarządzania

Tablet bezprzewodowy QIT30. Oprogramowanie Macro Key Manager

Instrukcja instalacji certyfikatu kwalifikowanego w programie Płatnik. wersja 1.8

Ćwiczenie 1 Automatyczna animacja ruchu

Certyfikat niekwalifikowany zaufany Certum Silver. Instrukcja dla uŝytkowników Windows Vista. wersja 1.1 UNIZETO TECHNOLOGIES SA

Ćwiczenie 1. Kolejki IBM Message Queue (MQ)

54. Układy współrzędnych

Serwis jest dostępny w internecie pod adresem Rysunek 1: Strona startowa solidnego serwisu

Zadanie 1. Stosowanie stylów

Obsługa grafiki w Delphi, rysowanie na płótnie, obsługa myszki, zapisywanie obrazków do plików, bitmapy pozaekranowe.

Programowanie w środowisku Windows. mgr inż. Krzysztof Mossakowski k.mossakowski@mini.pw.edu.pl

Dane słowa oraz wyrażenia są tłumaczone przy pomocy polecenia Przetwarzanie > Tłumaczenie

Komputery I (2) Panel sterowania:

Jak dodać własny szablon ramki w programie dibudka i dilustro

Załącznik 1 instrukcje instalacji

Obszar Logistyka/Zamówienia Publiczne

Jeżeli pole Krawędź będzie zaznaczone uzyskamy obramowanie w całej wstawianej tabeli

Papyrus. Papyrus. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Programowanie obiektowe

Dodawanie operacji dodatkowych w WAPRO Mag.

Transkrypt:

Podstawowy projekt OpenGL utworzony przy użyciu środowisk programistycznych firmy Microsoft. Autor: Radosław Płoszajczak Spis treści I. Wymagania i utworzenie projektu w Visual Studio 2005...2 II. Absolutne minimum...2 III. Wzbogacenie aplikacji o interakcję z użytkownikiem i animację...7

I. Wymagania i utworzenie projektu w Visual Studio 2005 Narzędzia Microsoft wymagane do utworzenia aplikacji OpenGL dla Windows: Microsoft Visual Studio, Microsoft Visual C++ lub Microsoft Visual C++ Express Edition + Microsoft Windows SDK (na dzień dzisiejszy najnowsza wersja to Windows Server 2003 R2 Platform SDK ok.400mb) Aby utworzyć projekt w Visual Studio 2005 należy z menu File wybrać New Project, z listy Project Type wskazać Visual C++ Win32 i następnie z listy Template wybrać Win32 Project. Po wprowadzeniu nazwy i zatwierdzeniu typu projektu pojawi się okno kreatora. W zakładce Application Settings w polu Application Type należy wybrać Windows Application i w Additional Options zaznaczyć opcję Empty Project. W ustawieniach projektu Project Properties z drzewa po lewej stronie wybieramy Configuration Properties Linker Input i w polu Additional Dependiences należy dopisać dodatkowe biblioteki: opengl32.lib glu32.lib. Domyślnie w Visual Studio 2005 programy kompilowane są dla kodowania Uncicode w Windows dlatego warto zmienić te ustawienie ponieważ biblioteka OpenGL w większości używa kodowania 1-bajtowego. Aby ustawić powyższe kodowanie należy w oknie ustawień projektu wybrać po lewej stronie Configuration Properties General zmienić opcję Character set z Use Unicode Character Set na Use Multibyte Character Set. W tak utworzonym projekcie należy kliknąć prawym przyciskiem na folderze Source files i z menu podręcznego wybrać Add New item... i dodać do projektu nowy plik źródłowy C++File (.cpp). II. Absolutne minimum Schemat postępowania: 1. Dodanie plików nagłówkowych #include <windows.h> #include <gl\gl.h> #include <gl\glu.h> 2. Stałe i zmienne globalne. HGLRC hrc = NULL; //uchwyt kontekstu renderingu HDC uchwytdc = NULL; //uchwyt prywatnego kontekstu urządzenia GDI GLint ClientWidth; //szerokość obszaru roboczego okna GLint ClientHeight; //wysokość obszaru roboczego okna static LPCTSTR lpszappname = "GLTemplate"; //nazwa okna i klasy okna Powyższe zmienne globalne zostaną wykorzystane w dalszej części tego tutorialu. Nazwę typu LPCTSTR można rozwinąć jako long pointer to TCHAR string czyli standardowy wskaźnik na tablicę znaków 1- lub 2-bajtowych (w zależności od ustawień środowiska) zakończonych /0. 3. Utworzenie funkcji WinMain(), która jest odpowiednikiem funkcji main() w aplikacjach konsolowych. Jej sygnatura jest następująca: int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) Znaczenie poszczególnych parametrów: HINSTANCE hinstance identyfikator danej instancji aplikacji HINSTANCE hprevinstance nie używane w aplikacjach Win32 Radosław Płoszajczak 2

LPSTR lpcmdline wskaźnik na listę parametrów int ncmdshow wartość określająca czy aplikacja ma zostać uruchomiona zminimalizowana, zmaksymilizowana itp. 4. Schemat funkcji WinMain(): 1. Deklaracja struktur klasy okna (WNDCLASS wc) i komunikatu dla okna (MSG msg) oraz zmiennej przechowującej uchwyt okna (HWND hwnd). 2. Wypełnienie struktyry klasy okna i jej zarejestrowanie dla danej aplikacji. wc.style = CS_HREDRAW CS_VREDRAW CS_OWNDC; //styl okna wc.lpfnwndproc = (WNDPROC)WndProc; //procedura okna wc.cbclsextra = 0; //dodatkowe bajty zarezerwowane za klasą okna wc.cbwndextra = 0; //dodatkowe bajty zarezerwowane za instancją okna wc.hinstance = hinstance; //instancja aplikacji wc.hicon = NULL; //uchwyt ikony wc.hcursor = LoadCursor(NULL, IDC_ARROW); //uchwyt kursora wc.hbrbackground = NULL; //uchwyt pędzla tła wc.lpszmenuname = NULL; //nazwa menu wc.lpszclassname = lpszappname; //nazwa klasy okna //Rejestracja klasy okna if(registerclass(&wc) == 0) return FALSE; Styl klasy okna określa pewne jego specyficzne właściwości. Są to wartości zdefiniowane w stałych zaczynających się przedrostkiem CS_ i mogą one być ze sobą łączone bitowym operatorem logicznym lub. W tym przypadku CS_HREDRAW i CS_VREDRAW wymuszają przerysowanie okna gdy zostanie zmieniony jego obszar roboczy na skutek zmiany rozmiaru okna lub pozycji okna (np. odsłonięcie jego części) odpowienio dla szerokości i wysokości. Ważne jest również aby okno posiadało własny unikalny kontekst urządzenia, którego nie utraci podczas całego czasu istnienia okna tej klasy (CS_OWNDC). Pole procedury okna przechowuje wskaźnik do funkcji procedury okna, która zostanie omówiona w dalszej części tutorialu. Dodatkowe bajty zarezerwowane za klasą i instanją okna wykożystywane są w innych bardziej zaawansowanych technikach programowania w WinAPI i w tym prostym przykładzie nie są potrzebne. Instancja aplikacji musi być taka sama jak, tej która posiada procedurę okna. Jej wartość pobierana jest z paremetru funkcji WinMain(). Uchwyt ikony pozwala na załadowanie własnej ikony dla okna. Wartośc NULL powoduje użycie domyślnej ikony Windows. Uchwyt kursora załadowany jest poprzes funkcję LoadCursor(), która w tym przypadku wybiera domyślną strzałkę. Uchwyt pędzla tła ustawiany jest na NULL co wymusza na aplikacji samodzielne odrysowanie tła. Wybranie jakiegokolwiek pędzla mogłoby spowodować migotanie przy odrysowywaniu sceny OpenGL. Nazwa głównego menu jest wskaźnikiem na zakończony zerem ciąg znaków identyfikujący zasób aplikacji (resurce) zawierający definicję menu. W tym przypadku okno nie ma menu więc wartośc ta jest ustawiana na NULL. Nazwa klasy okna jest wskaźnikiem na zakończony zerem łańcuch znaków i może on być taki sam jak nazwa okna. Po wypełnieniu wszystkich pól struktury wc funkcja RegisterClass() rejestruje klasę okna i w przypadku niepowodzenia zwraca 0. Radosław Płoszajczak 3

3. Utworzenie okna przy pomocy zarejestrowanej jego klasy. Funkcja CreateWindow() tworzy okno i zwraca jego uchwyt: hwnd = CreateWindow( lpszappname, //nazwa klasy okna lpszappname, //nazwa okna WS_OVERLAPPEDWINDOW WS_CLIPCHILDREN WS_CLIPSIBLINGS, //styl okna 100, 100, //położenie okna (x,y) 250, 250, //rozmiar okna (szerokość, wysokość) NULL, //uchwyt okna nadrzędnego (parent) NULL, //uchwyt menu hinstance, //uchwyt instancji aplikacji NULL); //parametr tworzenia okna if(hwnd == NULL) return FALSE; Nazwa klasy okna musi być taka sama jak ta zdefiniowana w strukturze zarejestrowanej klasy okna. Nazwa okna jest wskaźnikiem na zakończony zerem łańcuch znaków i w przypadku gdy okno posiada pasek tutułowy jest na nim wyświetlana. Styl okna podobnie jak styl klasy okna określa jego wygląd i pewne właściwości. Podobnie jak wcześniej definiuje się je łącząc wartości stałych lecz tym razem rozpoczynających się przedrostkiem WS_. Można tutaj ustalić czy okno ma posiadać pasek tytułowy, paski przewijania, przyciski minimalizacji, maksymalizacji, zamknięcia itp. Stała WS_OVERLAPPEDWINDOW określa połączenie kilku innych styli definiujących standardowe okno zawierające pasek tutułu, obramowanie, menu systemowe, przyciski maksymalizacji i minimalizacji itd. Najprostrze okno OpenGL musi posiadać dwa dodatkowe style aby aplikacja zawsze prawidłowo działała: WS_CLIPCHILDREN (wyklucza obszar zasłaniany przez okno podrzędne np. okno narzędziowe podczas odrysowywania okna głównego) oraz WS_CLIPSIBLINGS, które ma podobne znaczenie ale w odniesieniu do innych okien podrzędnych ( rodzeństwa ). Położenie okna liczone jest w pikselach i określa współrzędną lewego, górnego rogu okna liczoną od lewego, górnego rogu ekranu. Rozmiar okna podawany jest również w pikselach. W przypadku gdyby tworzone okno było oknem podrzędnym należy określić uchwyt okna nadrzędnego. W tym przypadku dane okno jest oknem głównym i parametr ten przyjmuje wartość NULL. Ponieważ okno nie ma posiadać menu uchwyt menu przyjmuje wartość NULL. Uchwyt instancji aplikacji wskazuje moduł programu, do którego ma należeć okno. W powyższym przykładzie wartośc ta jest pobierana z parametru funkcji WinMain(). Parametr tworzenia okna jest wskaźnikiem na parametr przekazywany procedurze okna WndProc() przez lparam podczas zajścia zdarzenia (WM_CREATE). Jeżeli zwrócony przez funkcję uchwyt okna hwnd ma wartość NULL oznacza to błąd i okno nie zostanie utworzone. 4. Pokazanie i zaktualizowanie okna. ShowWindow(hWnd,SW_SHOW); UpdateWindow(hWnd); Obie funkcje przyjmują jako parametr uchwyt okna hwnd jednoznacznie identyfikujący okno. Stała SW_SHOW aktywuje i pokazuje okno w jego dotychczasowym rozmiarze. Możliwe jest też zastosowanie innych stałych z przedrostkiem SW_ jak np. SW_SHOWMAXIMIZED, która to wyświetla zmaksymalizowane okno. Radosław Płoszajczak 4

5. Pętla komunikatów. while(getmessage(&msg, NULL, 0, 0)) TranslateMessage(&msg); DispatchMessage(&msg); Jest to główne miejsce, które odbiera i przesyła komunikaty dla okna pochodzące od systemu Windows i użytkownika takich jak zmiana rozmiaru okna, potrzeba jego odrysowania, kliknięcia myszką, naciśniecia klawiszy itd. Komunikaty te są obsługiwane przez procedurę okna WndProc(), która zostanie opisana w dalszej części tego tutoriala. Funkcja GetMessage() pobiera kolejny komunikat z kolejki komunikatów przesłanych przez system operacyjny. W przypadku gdy funkcja odbierze komunikat WM_QUIT oznaczający zakończenie aplikacji zwraca wartość FALSE i przerywa pętle. Przyjmuje ona 4 parametry: wskaźnik do struktury, w której zapisany zostanie komunikat uchwyt okna, dla którego komunikat ma zostać pobrany w tym przypadku wartość NULL oznacza, że komunikat ma zostać pobrany dla dowolnego okna aplikacji ostatnie dwa parametry wmsgfiltermin i wmsgfiltermax określają zakres filtru wiadomości w kolejce i w przypadku gdy oba maja wartość 0 żaden filtr nie jest stosowany. Funkcja TranslateMessage() tłumaczy wirtualne kody klawiszy uwzględniając przy tym m.in. stan klawisza shift oraz ustawienia regionalne systemu na odpowiednie kody znakowe. Następnie wstawia w kolejkę komunikat WM_CHAR z odpowiednim znakiem. Ma to znaczenie gdy w aplikacji ma np. następować wprowadzanie tekstu z klawiatury. DispatchMessage() wysyła podany w parametrze komunikat do odpowiedniej procedury okna. 6. Zwrócenie wartości podczas zakończenia programu. return msg.wparam; Na konieć funkcji WinMain() warto zwrócić do systemu kod zakończenia aplikacji zawarty w parametrze komunikatu WM_QUIT. 5. Utworzenie procedury okna mającej za zadanie obsługę komunikatów wysyłanych przez system operacyjny do okna aplikacji. Jej deklaracja jest następująca: LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); Funkcja ta zwraca wartość typu LRESULT co odpowiada standardowemu typowi long i zazwyczaj wynosi 0. Przyjmuje ona 4 parametry: uchwyt okna hwnd, którego aktualnie przetwarzany komunikat dotyczy, typ komunikatu message oraz dwa parametry tego komunikatu wparam i lparam. 6. Schemat podstawowej procedury okna OpenGL. switch (message) case WM_CREATE: //Utworzenie okna uchwytdc = GetDC(hWnd); GL_UstalFormatPikseli(uchwytDC); //Utworzenie kontekstu renderowania i uczynienie go aktywnym hrc = wglcreatecontext(uchwytdc); wglmakecurrent(uchwytdc, hrc); GL_UstawienieSceny(); Radosław Płoszajczak 5

case WM_DESTROY: //Usuwanie okna, czyszczenie //Usunięcie kontekstu renderowania wglmakecurrent(uchwytdc,null); wgldeletecontext(hrc); //Wysłanie komunikatu zamknięcia aplikacji WM_QUIT PostQuitMessage(0); case WM_SIZE: //Zmiana rozmiaru okna RECT rect; GetClientRect(hWnd, &rect); ClientHeight = rect.bottom rect.top; ClientWidth = rect.right rect.left; GL_UstawienieSceny(); case WM_PAINT: //Okno wymaga odrysowania GL_RysujScene(); ValidateRect(hWnd,NULL); default: //przetworzenie automatyczne pozostałych komunikatów return (DefWindowProc(hWnd, message, wparam, lparam)); return (0L); W najprostrzej postaci procedura okna posiada jedynie instrukcję switch, w której w zależności od rodzaju komunikatu wykonywane są odpowiednie czynności. Komunikat WM_CREATE przekazywany jest po utworzeniu okna i może on odpowiadać konstruktorowi klasy GLForm. Po jego odebraniu tworzony jest uchwyt urządzenia uchwytdc przy pomocy funkcji GetDC(), która jako parametr przyjmuje uchwyt okna dla którego jest on pobierany. Następnie na jego podstawie pobierany jest odpowiedni format pikseli przy pomocy funkcji GL_UstalFormatPikseli(), która ma taką sama postać jak ta w klasie GLForm. Kolejną czynnością jest utworznie kontekstu renderowania przy pomocy funkcji wglcreatecontext() i uczynienie go aktywnym poprzez wywołanie funkcji wglmakecurrent(). Gdy okno posiada już możliwość rysowania przy pomocy OpenGL można zainicjować ustawienia sceny funkcją GL_UstawieniaSceny() skopiowanej również z klasy GLForm. W momencie zamknięcia okna do procedury okna wysyłany jest komunikat WM_DESTROY. Analogicznie jak w poprzednim przypadku jest on odpowiednikiem destruktora klasy GLForm i przy jego obsłudze należy nieco "posprzątać". Najpierw należy sprawić aby kontekst renderowania nie był już aktywny podając w parametrze funkcji wglmakecurrent() uchwyt kontekstu renderowania jako NULL. Następnie należy usunąć kontekst renderowania przy pomocy funkcji wgldeletecontext(). Kolejną istotną sprawą jest sprawienie aby zamknięcie okna spowodowało zamknięcie całej aplikacji czyli przerwanie pętli komunikatów. Służy temu funkcja PostQuitMessage() z parametrem o wartości 0 co oznacza brak błędów. W przypadku gdy istnieje możliwość zmiany rozmiaru okna trzeba obsłużyć jego wpływ na wygląd rysowanej sceny w komunikacie WM_SIZE. W tym celu należy obliczyć rozmiar obszaru roboczego okna (bez obramowania i pasku tytułu). Aby tego dokonać należy wywołać funkcję GetClientRect(), która pobiera współrzędne (lewa, prawa, góra, dół) prostąkąta roboczego okna. Następnie obliczająć odpowienie różnice można otrzymać wysokość ClientHeight oraz szerokość ClientWidth obszaru roboczego. Wartości te bedą wykorzystywane przez funkcję GL_UstawieniaSceny() do określenia rozmiaru widoku. Ostatni komunikat WM_PAINT wysyłąny jest za każdym razem gdy okno wymaga Radosław Płoszajczak 6

odrysowania. Obsługa tego komunikatu polega na wywołaniu funkcji GL_RysujScene(). Wywołanie komunikatu WM_PAINT jest powiązane z unieważnieniem obszaru okna. Aby poprawnie odrysować okno należy na końcu zatwierdzić obszar roboczy okna. Służy temu funkcja ValidateRect(), która jako parametry przyjmuje uchwyt okna oraz wskaźnik do struktury RECT przechowującej współrzędne zatwierdzonego obszaru roboczego okna. Wartość NULL wymusza zatwierdzenie całej powierzchni roboczej. 7. Skopiowanie potrzebnych funkcji z klasy GLForm. Najpierw przed funkcją WinMain() należy zadeklarować odpowiednie funkcje: bool GL_UstalFormatPikseli(HDC uchwytdc); void GL_UstawienieSceny(void); void fastcall GL_RysujScene(void); void fastcall RysujScene(void); Następnie w dalszej części pliku źródłowego należy skopiować ciała tych funkcji. W przypadku funkcji RysujScene() należy w jej ciele zapisać dowolny kod rysujący OpenGL. Aby kompilacja aplikacji była możliwa należy wprowadzić kilka zmian w powyższych funkcjach. Dla uproszczenia tego opisu aplikacja zostanie również pozbawiona pewnych możliwości. W funkcji GL_UstawienieSceny() należy wykomentować wywołanie fuknkcji GL_Oswietlenie(). W funkcji GL_RysujScene() należy zmienić wywołanie funkcji glclearcolor() tak aby nie używała zmiennej kolortla: glclearcolor(0.0f, 0.0f, 0.0f, 0.0); Kolejnym krokiem aby aplikacja mogła się skompilować jest zdefiniowanie i zainicjowanie na początku pliku zmiennych globalnych kamery wykorzystywanych w funkcji : GLfloat kamerax = 0.0f; GLfloat kameray = 0.0f; GLfloat tmpkamerax = 0.0f; GLfloat tmpkameray = 0.0f; GLfloat kameraphi = 0.0f; GLfloat kameratheta = 0.0f; GLfloat tmpkameraphi = 0.0f; GLfloat tmpkameratheta = 0.0f; III. Wzbogacenie aplikacji o interakcję z użytkownikiem i animację. 1. Dodanie obrotu i przesunięcia kamery kontrolowanej przez mysz. Na początku procedury okna WndProc() należy zadeklarować statyczne zmienne, które będą przechowywać pozycję myszy w momencie kliknięcia prawego lub lewego przycisku, a później ostatnią pozycję myszy: static int x0 = 0; static int y0 = 0; Następnie należy do instrukcji switch wybierającej aktualnie przetwarzany komunikat dodać reakcję na naciśniecie lewego lub prawego przycisku myszy. Poniższe instrukcje zapiszą początkową pozycję myszy: case WM_RBUTTONDOWN: case WM_LBUTTONDOWN: x0 = LOWORD(lParam); y0 = HIWORD(lParam); Radosław Płoszajczak 7

Makra LOWORD() i HIWORD() wyodrębniają mniej i bardziej znaczące bajty parametru lparam odpowiadające współrzędnych myszy x i y. Kolejnym krokiem jest zaimplementowanie reakcji okna na ruch myszy co wymaga dodanie kolejnego zdarzenia do instrukcji switch: case WM_MOUSEMOVE: int x = LOWORD(lParam); int y = HIWORD(lParam); int dx = x x0; int dy = y y0; if (wparam == MK_RBUTTON) const GLfloat czulosc = 50.0f; kamerax += (GLfloat)dx / czulosc; kameray -= (GLfloat)dy / czulosc; if (wparam == MK_LBUTTON) const GLfloat czulosc = 5.0f; kameraphi += (GLfloat)dx / czulosc; kameratheta += (GLfloat)dy / czulosc; x0 = x; y0 = y; GL_RysujScene(); Na początku podobnie jak w przypadku naciśniecia przycisku myszy pobierana jest aktualna pozycja myszy. Następnie do zmiennych dx i dy zapisane są przesunięcia kursora myszy wzdłuż osi x i y okna. Parametr wparam tego zdarzenia zawiera informacje czy i jaki przycisk myszy był naciśnięty w czasie kiedy mysz została poruszona. W momencie gdy był naciśnięty prawy przycisk MK_RBUTTON następuje przesunięcie kamery proporcjonalnie do przesunięcia kursora. Lewy przycisk MK_LBUTTON powoduje obrót kamery. Na końcu aktualne wpółrzędne kursora są zapisywane, a scena odrysowywana. 2. Dodanie animacji. Animowanie kamery można zaimplementować z wykorzystaniem timera, który co jakiś określony odcinek czasu będzie ją obracał. Aby utworzyć timer wywoływany 50 razy na sekundę w procedurze okna WndProc() w komunikacie WM_CREATE należy dodać nąstępującą instrukcję: SetTimer(hWnd, 1, 20, NULL); Pierwszy parametr jest uchwytem okna, z którym timer ma być powiązany. Drugi parametr jest identyfikatorem timera wykorzystywanym w przypadku gdy okno posiada wiele timerów. Trzeci parametr określa odstęp czasu wyrażony w milisekundach pomiedzy poszczególnymi wywołaniami komunikatu WM_TIMER. Ostatni parametr może posłużyć do przekazania wskaźnika do procedury timera, która zostanie wywołana za każdym razem gdy odliczanie się zakończy. Jest to alternatywa do zdarzenia WM_TIMER dlatego w tym przykładzie należy tu podać wartość NULL. W momencie zamknięcia okna przez użytkownika należy usunąć czasomierz dodając przed instrukcją PostQuitMessage(0) następującą linię: KillTimer(hWnd, 1); Radosław Płoszajczak 8

Funkcja KillTimer() przyjmuje jako parametry uchwyt okna oraz identyfikator timera. Na koniec należy napisać kod wywoływany podczas zakończenia odliczania. W tym celu w funkcji WndProc() należy dodać obsługę kolejnego zdarzenia dopisując do instrukcji switch kolejny przypadek: case WM_TIMER: kameraphi += 0.5f; GL_RysujScene(); Komunikat WM_TIMER przesyłany jest wraz ze identyfikatorem czasomierza zawartym w parametrze wparam, który jest niezbędny podczas obsługi wielu timerów. Parametr lparam zawiera wskaźnik do procedury czasomierza zdefiniowany w wywołaniu funkcji SetTimer(). Powyższy kod sprawia, że co 20ms kamera obraca się o 0,5. Radosław Płoszajczak 9