OGRE/Zalążek programu OGRE
Informacje ogólne
[edytuj]Poniżej opiszemy najprostszy program Ogre na którym mozna opierać się w późniejszym tworzeniu większego systemu. Jeżeli miałbyś utworzyć zalążek programu sugerujemy byś do swego pierwszego pliku .cpp wkleił zawartość kodu podanego w paragrafie "Wspólny". Upewnij się że także Twoje środowisko projektowe jest skonfigurowane zgodnie z opisem w rozdziale Środowisko projektowe. Jeżeli, a tak najczęściej jest w przypadku przykładów, korzystać chcesz z klasy ExampleApplication, nie zapomnij do konfiguracji kompilatora dodać katalogu $(OGRE_HOME)\samples\include jako jednego z katalogów z plikami źródłowymi. Po wklejeniu kodu przekompiluj zalążek programu i uruchom go by sprawdzić czy wszystko jest prawidłowo skonfigurowane.
Jądro programu
[edytuj]Jądro programu ma bardzo prostą definicję. W zasadzie robi dwie rzeczy:
- tworzy obiekt aplikacji
- uruchamia obiekt aplikacji
myApp App;
App.go();
Pozostałe czynności związane są z obsługą ewentualnych błędów i prawidłowym zakończeniem programu.
Ciekawiej jest w definicjach klasy w których musimy co najmniej nadpisać metodę createScene() ExampleApplication.
Nasza praca w głównej mierze polega na nadpisywaniu kolejnych metod różnych klas definiowanych przez Ogre.
Kody źródłowe jądra aplikacji różnią się nieco w zależności od tego w jakim chcemy użyć ich w środowisku systemu operacyjnego.
Linux
[edytuj]#include <Ogre.h> /* Wszystkie nagłówki OGRE */
#include "ExampleApplication.h"
#include <iostream> /* Umożliwia wypisywanie błędów na konsole */
// Dziedziczymy ExampleApplication
class MyApp : public ExampleApplication
{
protected:
public:
MyApp()
{
}
~MyApp()
{
}
protected:
/** createScene jest funkcją czysto wirtualną w ExampleApplication,
* nadpisujemy ją, aby nic nie robiła.
* Na początku tworzy ona pustą scenę.
**/
void createScene(void)
{
}
};
int main(int argc, char **argv)
{
MyApp App; // Tworzymy instancję naszej klasy
try
{
App.go(); // ExampleApplication dostarcza metodę go, która rozpoczyna rendering
return 0; // Zwraca 0 w przypadku powodzenia
}
catch (Ogre::Exception& e) // Przechwytuje wyjątki (błędy)
{
std::cerr <<"Wyjątek:\n";
std::cerr <<e.getFullDescription().c_str() <<"\n";
return 1; // Zwrócenie liczby różnej od zera oznacza niepowodzenie
}
}
MAC
[edytuj]Windows
[edytuj]#include "Ogre.h" /* Wszystkie nagłówki OGRE */
#include "ExampleApplication.h"
#include <windows.h> /* Umożliwia wypisywanie błędów */
// Dziedziczymy ExampleApplication
class MyApp : public ExampleApplication
{
protected:
public:
MyApp()
{
}
~MyApp()
{
}
protected:
/** createScene jest funkcją czysto wirtualną w ExampleApplication,
* nadpisujemy ją, aby nic nie robiła.
* Na początku tworzy ona pustą scenę.
**/
void createScene(void)
{
}
};
INT WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,INT)
{
MyApp App; // Tworzymy instancję naszej klasy
try
{
App.go(); // ExampleApplication dostarcza metodę go, która rozpoczyna rendering
return 0; // Zwraca 0 w przypadku powodzenia
}
catch (Ogre::Exception& e) // Przechwytuje wyjątki (błędy)
{
MessageBox( NULL, e.getFullDescription().c_str(), "Wyjątek!",
MB_OK | MB_ICONERROR | MB_TASKMODAL);
return 1; // Zwrócenie liczby różnej od zera oznacza niepowodzenie
}
}
Wspólny
[edytuj]Pewnie łatwo jest zauważyć, że różnice sa nikłe i dotyczą wywołania funkcji głównej main która w przypadku Windows ma nazwę WinMain i nieco inne parametry, oraz wyprowadzania błędów - w przypadku Linux-a na konsolę, w przypadku Windows na MessageBox.
Ponieważ jak powiedzieliśmy we wstępie Ogre jest w założeniu przeznaczony jako jednolity dla systemów Linux, MAC i Windows, także programy pisane przy jego pomocy powinny być tak napisane by mogły być kompilowane pod każdym z tych systemów. Dlatego też przy prostym zastosowaniu dyrektyw prekompilacji możemy utworzyć kod źródłowy niezależny od systemu operacyjnego w którym będziemy go kompilować. Dodatkowo wprowadziliśmy także pomoc dla niektórych kompilatorów C++ wymagających metody extern "C" oraz definicję OGRE_CHANGE1 która umożliwi nam tworzenie kodu współpracującego z różnymi wersjami Ogre. Nasz kod ma teraz postać:
#define OGRE_CHANGE1 ((1 << 16) | (1 << 8)) /* Przeznaczone do wykrywania wersji Ogre */
#include "Ogre.h" /* Wszystkie nagłówki OGRE */
#include "ExampleApplication.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 /* W zależności od systemu operacyjnego */
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#else
#include <iostream>
#endif
// Dziedziczymy ExampleApplication
class MyApp : public ExampleApplication
{
protected:
public:
MyApp()
{
}
~MyApp()
{
}
protected:
/** createScene jest funkcją czysto wirtualną w ExampleApplication,
* nadpisujemy ją, aby nic nie robiła.
* Na początku tworzy ona pustą scenę.
**/
void createScene(void)
{
}
};
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 /* W zalezności od systemu operacyjnego */
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
MyApp App; // Tworzymy instancję naszej klasy
try
{
App.go(); // ExampleApplication dostarcza metodę go, która rozpoczyna rendering
return 0; // Zwraca 0 w przypadku powodzenia
}
catch (Ogre::Exception& e) // Przechwytuje wyjątki (błędy)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 // W zależności od systemu operacyjnego
MessageBox( NULL, e.getFullDescription().c_str(), "Wyjątek!",
MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr <<"Wyjątek:\n";
std::cerr <<e.getFullDescription().c_str() <<"\n";
#endif
return 1; // Zwrócenie liczby różnej od zera oznacza niepowodzenie
}
}
#ifdef __cplusplus
}
#endif
Ten kod proponujemy wstawiać zawsze do pliku główny_plik_źródłowy_aplikacji.ccp w katalogu 'src' lub w folderze 'Source files' w przypadku środowiska Visual Studio bez SDK Wizard lub po wybraniu opcji "Empty application". W przypadku zastosowania SDK Wizard i opcji "Minimal application" lub "Standard application" kod źródłowy zalążka jest nieco inny:
Visual Studio i SDK Wizard
[edytuj]Aplikacja standardowa
[edytuj]W przypadku wyboru tej opcji wraz z opcją "Sample Framework" tworzone jest środowisko z pełni funkcjonalnym kodem programu Ogre, który po przekompilowaniu wyświetla trójwymiarową głowę ogra. W folderze "Source files" tworzone jest jądro aplikacji w postaci pliku nazwa_projektu.ccp.
Definicja klasy nazwa_projektuApp jest zapisany w pliku nazwa_projektu.h w folderze "Header Files". W definicji klasy znajduje się metoda tworząca kamerę, metoda tworząca scenę i metoda tworząca FrameListener-a. W tym samym pliku znajduje się także definicja klasy nazwa_projektuFrameListener posiadająca metodę frameStarted.
Plik nazwa_aplikacji.ccp
[edytuj]Zawartość pliku nazwa_aplikacji.ccp w przypadku zastosowania VS, VC++ i Ogre SDK Wizard oraz wybrania opcji "Standard Application":
#include "nazwa_aplikacji.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
// Create application object
App3App app;
SET_TERM_HANDLER;
try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
Plik nazwa_aplikacji.h
[edytuj]Zawartość pliku nazwa_projektu.h w przypadku zastosowania VS, VC++ i Ogre SDK Wizard oraz wybrania opcji "Standard Application":
#ifndef __nazwa_projektu_h_
#define __nazwa_projektu_h_
#include "ExampleApplication.h"
class nazwa_projektuFrameListener : public ExampleFrameListener
{
private:
SceneManager* mSceneMgr;
public:
nazwa_projektuFrameListener(SceneManager *sceneMgr, RenderWindow* win, Camera* cam)
: ExampleFrameListener(win, cam),
mSceneMgr(sceneMgr)
{
}
bool frameStarted(const FrameEvent& evt)
{
bool ret = ExampleFrameListener::frameStarted(evt);
return ret;
}
};
class nazwa_projektuApp : public ExampleApplication
{
public:
nazwa_projektuApp()
{
}
~nazwa_projektuApp()
{
}
protected:
virtual void createCamera(void)
{
// Create the camera
mCamera = mSceneMgr->createCamera("PlayerCam");
// Position it at 500 in Z direction
mCamera->setPosition(Vector3(0,0,80));
// Look back along -Z
mCamera->lookAt(Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
}
// Just override the mandatory create scene method
virtual void createScene(void)
{
Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
headNode->attachObject(ogreHead);
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
// Create a light
Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
}
// Create new frame listener
void createFrameListener(void)
{
mFrameListener= new nazwa_projektuFrameListener(mSceneMgr, mWindow, mCamera);
mRoot->addFrameListener(mFrameListener);
}
};
#endif // #ifndef __nazwa_projektu_h_
Aplikacja minimalna
[edytuj]Zawartość pliku nazwa_projektu.ccp w przypadku stosowania VS, VC++ i Ogre SDK Wizard oraz wybrania opcji "Minimal Application":
#include <Ogre.h>
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
// Create application object
//nazwa_projektuApp app;
SET_TERM_HANDLER;
try {
//app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif