Prvo da vas sve pozdravim, a sad krećemo na stvar (ovo mi je prvi tutorial pa ne zamjerite ako nešto nije ok) :
Napravio sam tutorial koji se bavi integriranjem OpenGL grafičkog API-ja u C++ (VCL) formu.
Prvo što vam treba za početak je C++ Builder (RAD STUDIO) te malo dobre volje, a poželjno je i nešto
znanja jer tutorial nije baš za potpune početnike.
OpenGL biblioteke ne treba skidati jer C++ Builder dolazi već sa tim bibliotekama koje moramo samo
uključiti u projekt.
Pa hajde da krenemo:
Prvo ćemo pokrenuti C++ Builder te otvoriti novi projekt:
Kliknemo na "New Project" zatim odaberemo C++ Builder Projects, a nakon toga VCL Forms Application.
Pojavit će se prazna forma (prozor), a sad ćemo u nju prvo postaviti main menu.
U donjem desnom kutu imamo "Tool Palette" gdje upisemo "main menu" (TMainMenu), odaberemo kontrolu i
postavimo na formu.
Dobiti ćemo malu ikonicu na formi koju je potrebno 2 put kliknuti da definiramo nazive
u glavnom meniju (nazivi se definiraju u prozoru sa svojstvima kontrola (properties) pod "Caption"
koja je obično u donjem lijevom kutu. (pogledati prve 2 slike kako treba main menu izgledati).
Nakon toga ćemo postaviti ploču (naziv kontrole: TPanel) na formu gdje ćemo pod svojstvima staviti
"Align" na "alClient" (to će popuniti cijelu formu sa panelom).
Nakon toga u gornjem desnom kutu (Project Manager) ćemo kliknuti (desni klik) na "#ime projekta.exe"
odabrati Add New -> Other gdje će se pojaviti novi prozor zatim odabrati C++ Builder Files te ćemo dodati
CPP File i Header File koje ćemo nazvati OGL_CPP.cpp (cpp file) i OGL_H.h (header file).
Nazive je moguće izmijeniti desnim klikom cpp ili header file na "rename" ili kod spremanja projekta (save all).
Sljedeća stvar:
Otvorimo OGL_H.h i upišemo ovo:
#ifndef OGL
#define OGL
#endif OGL
void OGL_init();
void OGL_stopRendering();
void OGL_renderTriangle(int angle);
void OGL_renderSquare(int angle);
Znači header file se sastoji od makronaredbi kojima (počinju sa # znakom) kojima definiramo jedinstveni naziv headera,
te od nekoliko funkcija koje ne vraćaju vrijednost (void funkcije), a služe za inicijalizaciju OpenGL sustava, prekid rendera i rendera
određeninh objekata (trokut i kvadrat u mom slučaju).
Sljedeća stvar koju ćemo uraditi je otvoriti OGL_CPP.cpp file i upisati sljedeći kod:
#include "OGL_H.h" // uključuje naš prije napravljen header file
#include "main.h" // uključuje header glavne VCL forme.
#include <vcl.h>
#include <GL/GL.h> // ove tri makronaredbe uključuju OpenGL API u CPP datoteku
#include <GL/glu.h>
#include <GL/glaux.h>
#pragma comment( lib, "opengl32.lib" ) // definiramo biblioteke koje ćemo koristiti (OpenGL biblioteke)
#pragma comment( lib, "glu32.lib" )
HDC hdc; // device context - strukture koja definiraju set grafičkih objekata
HGLRC hrc;
int PixelFormat;
// ---------------------------------------------------------------------------
void OGL_init() {
try {
// Postavi sve parametre OpenGL-a
hdc = GetDC(Form1->Panel1->Handle); // *** Postavljamo render handle na naš prije postavljeni Panel na formu,
// odnosno definiramo gdje će se (u kojoj kontroli) render odvijati.
// Postavke izlaznog formata za OpenGL
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), 1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER |
PFD_GENERIC_ACCELERATED, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
PixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, PixelFormat, &pfd);
// Postavi OpenGL render na naš panel
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
}
catch (...) {
MessageBox(Form1->Handle, L"Unable to initialize OpenGL!",
L"OpenGL Renderer Demonstration", MB_OK | MB_ICONSTOP);
exit(0); // ovo je u slučaju da inicijalizacija OpenGL-a ne uspije,
// onda program ispisuje poruku i isključuje se.
}
}
// ---------------------------------------------------------------------------
void OGL_stopRendering() {
// funkcija koja prekida render objekata
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.1,0.2,0.3,1.0);
glLoadIdentity();
SwapBuffers(hdc);
}
// ---------------------------------------------------------------------------
void OGL_renderTriangle(int angle) {
// funkcija koja prikazuje trokut, a ima ulazni parametar pocetni kut trokuta
glMatrixMode(GL_MODELVIEW);
glViewport(0, -100, Form1->Width, Form1->Height);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.1,0.2,0.3,1.0);
glRotatef(angle, 0, 0, 1);
glBegin(GL_TRIANGLES);
glColor3f(0.3,0.4,0.5); // boja trokuta
glVertex2f(-0.3, 0.0); // koordinate vertexa (točaka) u 2D koordinatnom sustavu
glVertex2f(0.3, 0.0); // koje će na kraju tvoriti trokut
glVertex2f(0.0, 0.6);
glEnd();
glFlush();
SwapBuffers(hdc);
}
// ---------------------------------------------------------------------------
void OGL_renderSquare(int angle) {
// funkcija koja prikazuje kvadrata, a ima ulazni parametar pocetni kut kvadrata
glMatrixMode(GL_MODELVIEW);
glViewport(0, -120, Form1->Width, Form1->Height);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.1,0.2,0.3,1.0);
glRotatef(angle, 0, 0, 1);
glBegin(GL_QUADS);
glColor3f(0.3,0.4,0.5); // boja kvadrata
glVertex2f(0.0, 0.0); // koordinate vertexa (točaka) koje će tvoriti kvadrat
glVertex2f(0.0, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, 0.0);
glEnd();
glFlush();
SwapBuffers(hdc);
}
Nakon što smo to sve napravili, spremimo sve datoteke (za svaki slučaj) i otvorimo main.h header glavne forme koji mora ovako izgledati (malo sam skratio), ubaciti ću
samo bitne stvari:
// ---------------------------------------------------------------------------
#ifndef mainH
#define mainH
// ---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.Menus.hpp>
#include "LMDControl.hpp"
#include "LMDCustomControl.hpp"
#include "LMDCustomPanel.hpp"
#include "LMDCustomTrackBar.hpp"
#include "LMDTrackBar.hpp"
#include <Vcl.ComCtrls.hpp>
// ---------------------------------------------------------------------------
class TForm1 : public TForm {
__published: //ovdje dodamo sve funkcije koje nam trebaju
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormResize(TObject *Sender);
void __fastcall ExitApplication1Click(TObject *Sender);
void __fastcall Rotatingtriangle1Click(TObject *Sender);
void __fastcall Rotatingsquare1Click(TObject *Sender);
void __fastcall Stoprendering1Click(TObject *Sender);
private: // ovdje nema nista
public: //pod public također
__fastcall TForm1(TComponent* Owner);
void __fastcall stopRendering(TObject *Object, bool &done);
void __fastcall renderTriangle(TObject *Object, bool &done);
void __fastcall renderSquare(TObject *Object, bool &done);
void __fastcall SetPixelFormatDescriptor();
};
// ---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
// ---------------------------------------------------------------------------
#endif
Kad to sredimo otvoriti ćemo main.cpp datoteku koja će na kraju ovako izgledati:
// ---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "main.h"
// ---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "LMDControl"
#pragma link "LMDCustomControl"
#pragma link "LMDCustomPanel"
#pragma resource "*.dfm"
#include "OGL_H.h"
#include <GL/GL.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
TForm1 *Form1;
int angle = 0;
// ---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::stopRendering(TObject * Object, bool &done) {
// Zaustavi rendering
done = true;
angle = 0;
OGL_stopRendering();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::renderTriangle(TObject *Object, bool &done) {
// Renderiraj trokut unutar ove funkcije
done = false;
if (angle > 360) {
angle = 0;
}
OGL_renderTriangle(angle += 2); // *** render trokuta ***
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::renderSquare(TObject *Object, bool &done) {
// Renderiraj trokut unutar ove funkcije
done = false;
if (angle > 360) {
angle = 0;
}
OGL_renderSquare(angle+=2); // *** render kvadrata ***
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender) {
OGL_init();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender) {
// Kod promjene veličine forme
GLfloat nRange = 200.0f;
glViewport(0, 0, ClientWidth, ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (ClientWidth <= ClientHeight)
glOrtho(-nRange, nRange, -nRange*ClientHeight / ClientWidth,
nRange*ClientHeight / ClientWidth, -nRange, nRange);
else
glOrtho(-nRange*ClientWidth / ClientHeight,
nRange*ClientWidth / ClientHeight, -nRange, nRange, -nRange, nRange);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::ExitApplication1Click(TObject *Sender) {
exit(0);
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::Rotatingtriangle1Click(TObject *Sender) {
// Render trokuta
Application->OnIdle = renderTriangle;
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::Rotatingsquare1Click(TObject *Sender) {
// Render kvadrata
Application->OnIdle = renderSquare;
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::Stoprendering1Click(TObject *Sender) {
// Zaustavi rendering
Application->OnIdle = stopRendering;
}
// ---------------------------------------------------------------------------
Nakon što smo sve napravili, sad pritisnite F9 ili odaberite "run" i to je to.