Witam!
Dopiero zaczynam swoją przygodę z programowaniem i potrzebuję takiej drobnej pomocy.
Mógłby ktoś mi pomóc przerobić głowę robota na czajnik?
Korzystałem z gotowej funkcji glutSolidTeapot ale nie do końca mi to wychodziło.
Byłbym bardzo wdzięczny za pomoc.
#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
using namespace std;
HDC g_HDC;
float angle = 0.0f;
float legAngle[2] = { 0.0f, 0.0f };
float armAngle[2] = { 0.0f, 0.0f };
bool fullScreen = false;
/* Funkcja: DrawCube
Cel: Rysuje kwadraty.
*/
void DrawCube(float xPos, float yPos, float zPos)
{
glPushMatrix();
glBegin(GL_POLYGON);
//glutSolidTeapot();
/* Górna twarz*/
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
/* Przód twarzy*/
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, -1.0f, 0.0f);
/* Prawy profil*/
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
/* Lewy profil*/
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
/* Dół*/
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
/* Tył*/
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, -1.0f, -1.0f);
glEnd();
glPopMatrix();
}
/* Funcja: DrawArm
Cel: Rysuje ramię
*/
void DrawArm(float xPos, float yPos, float zPos)
{
glPushMatrix();
/* Ustawia czerwony kolor*/
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(xPos, yPos, zPos);
/* Tworzy kostkę 1 x 4 x 1 */
glScalef(1.0f, 4.0f, 1.0f);
DrawCube(0.0f, 0.0f, 0.0f);
glPopMatrix();
}
/* Function: DrawHead
Purpose: Rysuje głowę
*/
void DrawHead(float xPos, float yPos, float zPos) // float zPos
{
glPushMatrix();
/* Ustawia biał kolor*/
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(xPos, yPos, zPos);
/* Tworzy kostkę 2 x 2 x 2 */
glScalef(2.0f, 2.0f, 2.0f);
DrawCube(0.0f, 0.0f, 0.0f);
glPopMatrix();
}
/* Function: DrawTorso
Purpose: Rysuję tłów
*/
void DrawTorso(float xPos, float yPos, float zPos)
{
glPushMatrix();
/* Ustawia kolor niebieski*/
glColor3f(0.0f, 0.0f, 1.0f);
glTranslatef(xPos, yPos, zPos);
/* Tworzy kostkę 3 x 5 x 1 */
glScalef(3.0f, 5.0f, 1.0f); //351
DrawCube(0.0f, 0.0f, 0.0f);
glPopMatrix();
}
/* Function: DrawLeg
Purpose: Rysję nogi
*/
void DrawLeg(float xPos, float yPos, float zPos)
{
glPushMatrix();
/* Ustawia kolor żółty*/
glColor3f(1.0f, 1.0f, 0.0f);
glTranslatef(xPos, yPos, zPos);
/* Tworzy kostke 1 x 5 x 1 */
glScalef(1.0f, 5.0f, 1.0f);
DrawCube(0.0f, 0.0f, 0.0f);
glPopMatrix();
}
/* Funcja: DrawRobot
Cel: Rysuje całego robota
*/
void DrawRobot(float xPos, float yPos, float zPos)
{
/* Zmienne kończyn robota.
True znaczy, że noga jest w przodzie,
False znaczy, że noga robota jest w tyle.
*/
static bool leg1 = true;
static bool leg2 = false;
static bool arm1 = true;
static bool arm2 = false;
glPushMatrix();
/* Rysuje robota w wyznaczonych współrzędnych.
*/
glTranslatef(xPos, yPos, zPos);
/* Te trzy linie rysują różne części naszego robota.
*/
//glutSolidTeapot(1);
DrawHead(1.0f, 2.0f, 0.0f);
DrawTorso(1.5f, 0.0f, 0.0f);
glPushMatrix();
/* Jeśli ręka robota rusza się w przód zwiększamy kąt;
W innym przypadku zmniejszamy kąt.
*/
if (arm1)
{
armAngle[0] = armAngle[0] + 1.0f;
}
else
{
armAngle[0] = armAngle[0] - 1.0f;
}
/* Kiedy ręka osiąga maksymalne wychylenie w jedną strone,
to chcemy, żeby poruszała się w drugą stronę.
*/
if (armAngle[0] >= 15.0f)
{
arm1 = false;
}
if (armAngle[0] <= 15.0f)
{
arm1 = true;
}
/* Oddzielamy rękę od tłowia.
Tworzymy efekt poruszania się.
*/
glTranslatef(0.0f, -0.5f, 0.0f);
glRotatef(armAngle[0], 1.0f, 0.0f, 0.0f);
DrawArm(2.5f, 0.0f, -0.5f);
glPopMatrix();
glPushMatrix();
/* Kiedy ręka osiąga maksymalne wychylenie w jedną strone,
to chcemy, żeby poruszała się w drugą stronę.
*/
if (arm2)
{
armAngle[1] = armAngle[1] + 1.0f;
}
else
{
armAngle[1] = armAngle[1] - 1.0f;
}
/* Oddzielamy rękę od tłowia.
Tworzymy efekt poruszania się.
*/
glTranslatef(0.0f, -0.5f, 0.0f);
glRotatef(armAngle[1], 1.0f, 0.0f, 0.0f);
DrawArm(-1.5f, 0.0f, -0.5f);
glPopMatrix();
/* Obracamy nogę w zależności od położenia ciała.
*/
glPushMatrix();
/* Jeśli noga porusza się do przodu to zwiększamy kąt,
jeśli nie to zmniejszamy.
*/
if (leg1)
{
legAngle[0] = legAngle[0] + 1.0f;
}
else
{
legAngle[0] = legAngle[0] - 1.0f;
}
/* Kiedy noga osiąga maksymalne wychylenie w jedną strone,
to chcemy, żeby poruszała się w drugą stronę.
*/
if (legAngle[0] >= 15.0f)
{
leg1 = false;
}
if (legAngle[0] <= -15.0f)
{
leg1 = true;
}
/* Oddzielamy nogę od tłowia.
Tworzymy efekt poruszania się.
*/
glTranslatef(0.0f, -0.5f, 0.0f);
glRotatef(legAngle[0], 1.0f, 0.0f, 0.0f);
/* Czas narysować nogę :)
*/
DrawLeg(-0.5f, -5.0f, -0.5f);
glPopMatrix();
/* Tak samo jak wyżej, dla lewej nogi.
*/
glPushMatrix();
/* Jeśli noga porusza się do przodu to zwiększamy kąt,
jeśli nie to zmniejszamy.
*/
if (leg2)
{
legAngle[1] = legAngle[1] + 1.0f;
}
else
{
legAngle[1] = legAngle[1] - 1.0f;
}
/* Kiedy noga osiąga maksymalne wychylenie w jedną strone,
to chcemy, żeby poruszała się w drugą stronę.
*/
if (legAngle[1] >= 15.0f)
{
leg2 = false;
}
if (legAngle[1] <= -15.0f)
{
leg2 = true;
}
/* Oddzielamy nogę od tłowia.
Tworzymy efekt poruszania się.
*/
glTranslatef(0.0f, -0.5f, 0.0f);
glRotatef(legAngle[1], 1.0f, 0.0f, 0.0f);
DrawLeg(1.5f, -5.0f, -0.5f);
glPopMatrix();
glPopMatrix();
}
/* Funcja: Render
Cel: Będzie renderować :)
*/
void Render()
{
/* Włącza destowanie głębi.
*/
glEnable(GL_DEPTH_TEST);
/* To nasze renderowanie, czyści ekran na czarno, czyści kolor i głębię
i resetuje macierz widokową(modelu).
*/
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
/* Zwiększenie obrotów licznika kąta
*/
angle = angle + 1.0f;
/* Reset, kiedy osiągneliśmy koło
*/
if (angle >= 360.0f)
{
angle = 0.0f;
}
glPushMatrix();
glLoadIdentity();
/* Rusz z 0,0,-30 , obraca robota na osi y, rysuj robota, i wyświetl aktualną macierz.
*/
glTranslatef(0.0f, 0.0f, -30.0f);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
DrawRobot(0.0f, 0.0f, 0.0f);
glPopMatrix();
glFlush();
/* Przywraca buffer do tła.
*/
SwapBuffers(g_HDC);
}
/* Funcja: SetupPixelFormat
Cel: Funkcja ta będzie odpowiedzialna
ustalania formatu dla piksela kontekstu urządzenia.
*/
void SetupPixelFormat(HDC hDC)
{
/* Format pixela index.
*/
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), //Rozmiar struktury
1, //Wersja domyślna
PFD_DRAW_TO_WINDOW | //Wsparcie rysowania okna
PFD_SUPPORT_OPENGL | //Wsparcie opengl
PFD_DOUBLEBUFFER, //Wsparcie dla podwójnego bufforowania
PFD_TYPE_RGBA, //RGBA tryb koloru
32, //32 bitowy tryb koloru
0, 0, 0, 0, 0, 0, //Ignoruj bity koloru.
0, //Brak alpha buffera
0, //Ignoruj bit zmiany
0, //Brak buffera gromadzenia
0, 0, 0, 0, //Ignoruje buffer gromadzenia
16, //16 bitowy rozmiar z-buffera
0, //Brak szablonu buffera
0, //Brak aux buffera
PFD_MAIN_PLANE, //Główna płaszczyzna rysująca
0, //Odwrócony
0, 0, 0 }; //Ignoruje warsty masek.
/* Wybiera najlepiej pasujący format*/
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
/* Ustawia pixel format dla kontekstu urządzenia*/
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
/* Windows Event Procedure Handler
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
/* Rendering i zmienne kontekst urządzenia
są tutaj ustawiane.
*/
static HGLRC hRC;
static HDC hDC;
/* Szerokość i wysokość dla okna robota wyświetlana jest w.
*/
int width, height;
switch (message)
{
case WM_CREATE: //Utworzyliśmy okno
hDC = GetDC(hwnd); //Pobiera aktualne windows kontekst urządzenia
g_HDC = hDC;
SetupPixelFormat(hDC); //Wywołuje naszę funkcję pixel format
/* Tworzy rendering kontekstu i robi je aktualnym
*/
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return 0;
break;
case WM_CLOSE: //Okno zostało zamknięte
/* Odznacza rendering kontekst u usuwa je*/
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
/* Wysyła wiadomość wyjdź do kolejki.*/
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
/* Odzyskuje szerokość i wysokość*/
height = HIWORD(lParam);
width = LOWORD(lParam);
/* Nie chcesz chyba dzielić przez zero? :)*/
if (height == 0)
{
height = 1;
}
/* Zresetować rzutnię do nowych wymiarów*/
glViewport(0, 0, width, height);
/* Ustawia aktualną macierz do wyświetlania*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //Resetuję wyświetlanie macierzy
/* Obliczamy współczynnik okna.
*/
gluPerspective(54.0f, (GLfloat)width / (GLfloat)height, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW); //Ustawia macierz modelview
glLoadIdentity(); //Resetuję macierz modelview
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX windowClass; //klasa window
HWND hwnd; //Obługa okna
MSG msg; //wiadomość
bool done; //Informuje o ukończeniu
DWORD dwExStyle; //Roszerzony styl okna
DWORD dwStyle; //Styl okna
RECT windowRect;
/* Screen/atrybuty wyświetlania*/
int width = 800;
int height = 600;
int bits = 32;
windowRect.left = (long)0; //Ustaw lewą wartość na 0
windowRect.right = (long)width; //Ustawą prawą wartość dla porządanej szerokości
windowRect.top = (long)0; //Ustaw górną wartość na 0
windowRect.bottom = (long)height;//Ustawą dolną wartość dla porządanej wysokość
/* Wypełnij strukturę klasy okna.*/
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = "MyClass";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
/* Zarejestruj klasę okno*/
if (!RegisterClassEx(&windowClass))
{
return 0;
}
/* Sprawdź czy pełny ekran jest włączony*/
if (fullScreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; //Szerokość ekranu
dmScreenSettings.dmPelsHeight = height; //Wysokość ekranu
dmScreenSettings.dmBitsPerPel = bits; //bity na pixele
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN !=
DISP_CHANGE_SUCCESSFUL))
{
/* Ustawianie trybu wyświetlania nieudane, zamień na okienkowy*/
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
fullScreen = false;
}
}
/* Sprawdź czy pełny ekran jest ciągle właczony*/
if (fullScreen)
{
dwExStyle = WS_EX_APPWINDOW; //Roszerzony styl okna
dwStyle = WS_POPUP; //Styl okna
ShowCursor(FALSE); //Mouse pointer(klikacz)
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; //Roszerzony styl okna
dwStyle = WS_OVERLAPPEDWINDOW; //Styl okna
}
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
/* Rejestracja klasy, tworze okno*/
hwnd = CreateWindowEx(NULL, "MyClass", //Nazwa klasy
"OpenGL Robot", //Nazwa aplikacji
dwStyle |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0, //współrzędne x y
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top,//szerokość, wysokość
NULL, //Uchwyt źródła
NULL, //Uchwyt menu
hInstance, //Wystąpienie aplikacji
NULL); //no xtra params
/* Sprawdź czy tworzenie okna powiodło się (hwnd = null ?)*/
if (!hwnd)
{
return 0;
}
ShowWindow(hwnd, SW_SHOW); //Wyświetla okno
UpdateWindow(hwnd); //Aktualizuje okno
done = false; //Inicjalizuje zmienną warunkową pętli
/* Główne przesłanie pętli*/
while (!done)
{
PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT) //Otrzymaliśmy wiadomość wyjścia?
{
done = true;
}
else
{
Render();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (fullScreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(TRUE);
}
return msg.wParam;
}