OGRE/Zalążek programu OGRE

Z Wikibooks, biblioteki wolnych podręczników.

Spis treści

[edytuj] Informacje ogólne

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.

[edytuj] Jądro programu

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.

[edytuj] Linux

#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
  }
}

[edytuj] MAC

[edytuj] Windows

#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
   }
}

[edytuj] Wspólny

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:

[edytuj] Visual Studio i SDK Wizard

[edytuj] Aplikacja standardowa

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.

[edytuj] Plik nazwa_aplikacji.ccp

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

[edytuj] Plik nazwa_aplikacji.h

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_

[edytuj] Aplikacja minimalna

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