Archive for March 2009

IGK 2009 – podsumowanie

W tym roku wreszcie mogłem w pełni uczestniczyć na konferencji Inżynieria Gier komputerowych, która odbywała się w Siedlcach (W zeszłym roku byłem niestety tylko na jeden nocleg). Jest to jedyne w roku wydarzenie, w którym tak duża ilość ludzi z Warsztatu spotyka się w jednym miejscu.

Standardowym składnikiem konferencji są referaty, które są wygłaszane przez ludzi zarówno z Akademii Podlaskiej jak i ludzi z zewnątrz przez pierwsze dwa dni. Bardzo podobał mi się referat Jakuba Jastrzębskiego, który bardzo fajnie przedstawił swój referat, w którym zawarł informacje o rodzajach silników fizyki, przykładowej architekturze, implementacji własnych rozwiązań.
Również kolejnym ciekawy referat przedstawił Hubert Rutkowski, który poruszył w nim głównie problemy niezwiązane bezpośrednio z programowaniem, lecz z pracą przy komputerze, czyli problem bolących nadgarstków oraz szybkiego pisania. W swojej pracy polecił kilka ciekawych wtyczek do środowiska Microsoft Visual Studio.
Referat Karola Gasińskiego był także bardzo ciekawy. Omawiał on w swojej pracy wykorzystanie megatexturingu w renderingu planety z dynamicznym poziomem dokładności.
Ostatnim, a zarazem najlepszym referatem okazała się praca Wojciecha Tomana omawiająca jego dotychczasowy dorobek przy pracy nad silnikiem nGene. W swojej prezentacji zaprezentował sposób renderowania realistycznej wody jako efekt post-process, w której poszczególne składowe światła zanikają wraz ze wzrostem głębokości. Za swoją pracę otrzymał nagrodę za najlepszy referat ufundowaną przez firmę Seventhtear.

Niestety najsłabsze okazały referaty przedstawicieli Akademii Podlaskiej. Pierwszy, dotyczący implementacji trójwymiarowej gry zręcznościowej na telefon komórkowy, miał zbyt dużą ilość tekstu w prezentacji, a wygłaszający po prostu go czytał, jednak mimo tego gratuluje napisania działającej gry.
Natomiast drugi temat pt. “Rola języków skryptowych w technologii gier” owszem posiadał w miarę poprawną formę prezentacji, ale sprawiał wrażenie projektu na uczelnię, ponieważ prowadzący nie byli w stanie odpowiedzieć na pytanie zadane na końcu prezentacji.

W tym roku gościem specjalnym konferencji IGK, był przedstawiciel firmy The Farm 51, który przedstawił prezentację na temat ewolucji renderera i mechaniki ich najnowszej gry FPS Necrovision. Prezentacja była świetna, a prowadzący demonstrował wszystko w edytorze gry bądź na filmikach.

Tak jak w zeszłym roku i tym razem odbył się Quiz nt. IT, którego pomysłodawcą i prowadzącym jest Regedit. W tym roku jednak za zajęcie pierwszego miejsca były przyznawane nagrody rzeczowe. Najlepszy okazał się Krzysiek K., gratulacje :).

Ostatnim oficjalnym składnikiem konferencji był konkurs Compo, w którym należało napisać grę na temat: “Gra psychodeliczna”. W konkursie wzięło udział 9 drużyn, a tegorocznym zwycięzcą okazał się zespół Rzeźnicy Inc., w którego skład wchodzą: Krzysiek K., Regedit, gemGreg, Ayufan. Drugie i trzecie miejsce zajęły odpowiednio zespoły Kryzys oraz Vertex.

Oczywiście nie obyło się bez wieczorowych integracji, które miały miejsce w piątek i niedziele wieczorem, w pokoju grupy Vexillium. W trakcie tych integracji można było zagrać w takie gry jak Starcraft, Quake 3 Demo, Urban Terror oraz World of Goo :D. W niedziele wieczorem odbył się turniej Quake’a, w którym zająłem zaszczytne ostatnie miejsce :P, a oczywiście wygrał Gynvael, zresztą więcej na jego stronce.
Aktualnie zastanawia mnie tylko jedna sprawa, czy w przyszłym roku również będzie nas gościć hotel Arche (uczestnicy wiedzą ocb :)).

Ogólnie podsumowując, mam nadzieję że w przyszłym roku frajda z uczestnictwa będzie minimum taka jak w tym. Mam nadzieję, że jednak więcej osób zgłosi się z referatami, żeby było czego posłuchać :).

AutomaticHandle ciąg dalszy

Jak się okazuje nic nie jest na początku idealne. Dzięki uwagom Revo udało mi się usprawnić szablon automatycznych uchwytów. Revo poradził mi dodanie dodatkowego wskaźnika na licznik odwołań do danego zasobu. Dzięki temu możliwe było usunięcie jednej funkcji wirtualnej, a druga została sprowadzona do roli sprzątaczki, która zostaje wywołana tylko w momencie, gdy licznik osiąga wartość 0. Dodatkowo dodałem sprawdzenie czy uchwyt nie jest zerowy przed odwołaniem się do wskaźników.

Poniżej znajduję się kod poprawionej klasy szablonowej AutomaticHandle:

typedef unsigned int Dword;
 
template< typename TAG>
class AutomaticHandle
{
public:
	// Podstawowy konstruktor
	AutomaticHandle(NLib::Dword handle, MHandleMgr* manager, NLib::Dword* resCounter) : m_handle(handle), m_manager(manager), m_resCounter(resCounter)
	{ if(m_handle) ++(*m_resCounter); }
	// Konstruktor kopiujący
	AutomaticHandle(const AutomaticHandle& src) : m_manager(src.m_manager), m_handle(src.m_handle), m_resCounter(src.m_resCounter)
	{ if(m_handle) ++(*m_resCounter); }
	// Destruktor
	~AutomaticHandle()
	{
		if(m_handle)
		{ if(!(--(*m_resCounter))) m_manager->ReleaseResource(m_handle); }
	}
	// Operator przypisania
	const AutomaticHandle& operator =(const AutomaticHandle& src)
	{
		if(m_handle)
		{ if(!(--(*m_resCounter))) m_manager->ReleaseResource(m_handle); }
		m_handle = src.m_handle;
		if(m_handle) ++(*(m_resCounter = src.m_resCounter));
		return src;
	}
	// Operator równości
	bool operator ==(const AutomaticHandle& src)
	{ return m_handle == src.m_handle; }
	// Operator różności
	bool operator !=(const AutomaticHandle& src)
	{ return m_handle != src.m_handle; }
	// Operator Dword
	operator NLib::Dword() const
	{ return m_handle; }
	// Operator bool
	operator bool() const
	{ return !!m_handle; }
 
private:
	// Uchwyt
	NLib::Dword m_handle;
	// Wskaźnik do managera
	MHandleMgr* m_manager;
	// Wskaźnik do licznika zasobu
	NLib::Dword* m_resCounter;
};

Kolejną klasą jest AutoHandleMgr, czyli klasa implementująca obsługę automatycznych uchwytów. Aktualnie tylko trzy funkcje są dostępne klasie pochodnej, w tym jedna dla uchwytów. Klasa ta posiada jedną funkcję abstrakcyjną, w której po zdefiniowaniu w klasie pochodnej należy usuwać odpowiednie zasoby zgodnie z przekazanym indeksem.

Oto jej definicja:

typedef unsigned int Dword;
 
class AutoHandleMgr
{
	// Unia do wyciągania informacji z uchwytu
	enum
	{
		// Rozmiary pól
		MAX_BITS_INDEX = sizeof(NLib::Dword) * 4,
		MAX_BITS_MAGIC = sizeof(NLib::Dword) * 4,
		// Maksymalne wartości pól
		MAX_INDEX = (1 << MAX_BITS_INDEX) - 1,
		MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1
	};
 
public:
	// Funkcja do zwracania uchwytu
	void ReleaseResource(NLib::Dword handle)
	{
		NAssert(GetIndex(handle) < m_magicValues.size(), "Wrong Handle");
		NAssert(CheckMagic(handle), "Wrong handle");
		DeleteHandleAt(GetIndex(handle));
		ReleaseResourceByIndex(GetIndex(handle));
	}
 
protected:
	// Funkcja tworzy nowy uchwyt i go zwraca
	// Index zawarty w uchwycie odpowiada indeksowi w tablicy z danymi
	// w odziedziczonej klasie
	NLib::Dword CreateNewHandle()
	{
		NLib::Dword handle;
		static NLib::Dword s_autoMagic = 0;
		if(++s_autoMagic > MAX_MAGIC) s_autoMagic = 1;	// 0 oznacza pusty uchwyt
		// Jeżeli nie ma wolnych miejsc to tworze nowy index
		if(m_freeSlots.empty())
		{
			handle = m_magicValues.size() << (MAX_BITS_INDEX - 1);
			m_magicValues.push_back(s_autoMagic);
		}
		else
		{
			handle = m_freeSlots.back() << (MAX_BITS_INDEX - 1);
			m_magicValues[m_freeSlots.back()] = s_autoMagic;
			m_freeSlots.pop_back();
		}
		handle |= s_autoMagic;
		return handle;
	}
	// Funkcja zwraca index
	NLib::Dword GetIndex(NLib::Dword handle)
	{ return (handle >> (MAX_BITS_INDEX - 1)) & MAX_INDEX; }
 
private:
	// Funkcja kasuje wskazany uchwyt
	void DeleteHandleAt(NLib::Dword index)
	{	m_freeSlots.push_back(index);
		m_magicValues[index] = 0; }
	// Funkcja zwraca część magiczną
	NLib::Dword GetMagic(NLib::Dword handle)
	{ return handle & MAX_MAGIC; }
	// Funkcja sprawdzająca wartośc magic
	bool CheckMagic(NLib::Dword handle)
	{	NAssert(GetIndex(handle) < m_magicValues.size(), "Wrong Handle");
		return GetMagic(handle) == m_magicValues[GetIndex(handle)]; }
 
private:
	// Funkcja dekrementująca licznik w zasobach
	virtual void ReleaseResourceByIndex(NLib::Dword index) = 0;
 
private:
	// Vector zawierający magiczne wartości
	std::vector m_magicValues;
	// Vector zawierający indeksy z wolnymi miejscami
	std::vector m_freeSlots;
};

W przypadku tego menadżera uchwyty muszą być usunięte przed nim, inaczej pojawią się błędy z dostępem do pamięci.