OGRE/Zalążek programu OGRE

Z Wikibooks, biblioteki wolnych podręczników.

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