<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>GhurundEngine</title>
	<atom:link href="http://ghurundengine.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://ghurundengine.wordpress.com</link>
	<description>Strona silnika Ghurund</description>
	<lastBuildDate>Sun, 12 Feb 2012 14:11:31 +0000</lastBuildDate>
	<language>pl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='ghurundengine.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/ed042a1974cf64ed0df26628e3f38ec1?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>GhurundEngine</title>
		<link>http://ghurundengine.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://ghurundengine.wordpress.com/osd.xml" title="GhurundEngine" />
	<atom:link rel='hub' href='http://ghurundengine.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Cwaniacki preprocessor</title>
		<link>http://ghurundengine.wordpress.com/2012/02/11/cwaniacki-preprocessor/</link>
		<comments>http://ghurundengine.wordpress.com/2012/02/11/cwaniacki-preprocessor/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 18:20:16 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
		
		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=138</guid>
		<description><![CDATA[Preprocessor do C++ od dawna jest uważany za narzędzie niebezpieczne dla niedoświadczonych programistów. Głównym powodem takiej opinii jest fakt, że preprocessor operuje na tekście, a więc nie sprawdza, jak zachowa się kod podczas kompilacji i wykonania. Zastanówmy się, w jaki sposób można wykorzystać preprocessor bardziej po cwaniacku. Weźmy pierwszą lepszą konstrukcję, która może się wydawać przydatna przy pisaniu kodu: Obj *obj = getObj(); if(obj!=NULL){     obj-&#62;doSomething(); } Sprawa jest bardzo prosta, można by zautomatyzować odrobinę to sprawdzenie przez napisanie prostego makra: #define ifNotNull(p) if(p)p Od tej pory możemy [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=138&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Preprocessor do C++ od dawna jest uważany za narzędzie niebezpieczne dla niedoświadczonych programistów. Głównym powodem takiej opinii jest fakt, że preprocessor operuje na tekście, a więc nie sprawdza, jak zachowa się kod podczas kompilacji i wykonania.<span id="more-138"></span></p>
<p>Zastanówmy się, w jaki sposób można wykorzystać preprocessor bardziej po cwaniacku. Weźmy pierwszą lepszą konstrukcję, która może się wydawać przydatna przy pisaniu kodu:</p>
<pre style="padding-left:30px;"><span style="color:#33cccc;">Obj</span> *<span style="color:#008000;">obj</span> = <span style="color:#993300;">getObj</span>();
<span style="color:#0000ff;">if</span>(obj!=<span style="color:#ff00ff;">NULL</span>){
    <span style="color:#008000;">obj</span>-&gt;<span style="color:#993300;">doSomething</span>();
}</pre>
<p>Sprawa jest bardzo prosta, można by zautomatyzować odrobinę to sprawdzenie przez napisanie prostego makra:</p>
<pre style="padding-left:30px;"><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">ifNotNull</span>(<span style="color:#008000;">p</span>) <span style="color:#0000ff;">if</span>(<span style="color:#008000;">p</span>)<span style="color:#008000;">p</span></pre>
<p>Od tej pory możemy napisać:</p>
<pre style="padding-left:30px;"><span style="color:#ff00ff;">ifNotNull</span>(<span style="color:#993300;">getObj</span>())-&gt;<span style="color:#993300;">doSomething</span>();</pre>
<p>A teraz zastanówmy się nad potencjalnymi problemami. Oczywiście dobrą praktyką jest branie wszystkiego w nawiasy, chodź w tym przypadku trudno jest wykorzystać makro nieprawidłowo. Jest jednak większy problem. Co z sytuacją, gdy programista uwielbia konstrukcje anty-RISC i spróbuje podać bardziej skomplikowane wyrażenie jako parametr makra? Kod zostanie wykonany tyle razy, ile razy się pojawia w makrodefinicji, tj. w naszym przypadku 2.</p>
<p>Otóż dochodzimy do cwaniackiego rozwiązania. Wykorzystamy nieco bardziej egzotyczne elementy języka, mianowicie aktualną linię (__LINE__), operator sklejania (##) i automatyczne dobieranie typu zmiennej (auto) będące częścią nowego standardu C++. Definicja __LINE__ jest zastępowana aktualnym wierszem w kodzie, a więc możemy ją wykorzystać do zadeklarowania dowolnej zmiennej o dosyć bezpiecznym identyfikatorze. Bezpiecznym, tj. unikatowym w najbliższej okolicy. Dopóki jesteśmy w tym samym wierszu, możemy swobodnie używać tak stworzonego identyfikatora do naszych potrzeb. Najważniejszą potrzebą jest zapisanie wyniku potencjalnych obliczeń przekazanych jako argument:</p>
<pre style="padding-left:30px;"><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">ifNotNull</span>(<span style="color:#008000;">p</span>) <span style="color:#0000ff;">auto</span> *<span style="color:#008000;">s</span>##<span style="color:#ff00ff;">__LINE__</span>=<span style="color:#008000;">p</span>;<span style="color:#0000ff;">if</span>(<span style="color:#008000;">s</span>##<span style="color:#ff00ff;">__LINE__</span>)<span style="color:#008000;">s</span>##<span style="color:#ff00ff;">__LINE__</span></pre>
<p>Co się dzieje? Oczywiście nie działa. A dlaczego? Bo operator sklejania bierze __LINE__ jako tekst o treści &#8216;__LINE__&#8217; i dokleja go do &#8216;s&#8217; tworząc &#8216;s__LINE__&#8217;.  Winny jest operator sklejania, a do obejścia tego problemu trzeba wprowadzić dwa dodatkowe makra opakowujące konkatenację. Uprzedzając pytanie &#8211; jedno nie wystarcza. Teraz mamy tak:</p>
<pre style="padding-left:30px;"><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">CONCATENATE</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>) <span style="color:#008000;">x</span>##<span style="color:#008000;">y
</span><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>) <span style="color:#ff00ff;">CONCATENATE</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>)
<span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">ifNotNull</span>(<span style="color:#008000;">p</span>) <span style="color:#0000ff;">auto</span> *<span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">s</span>,<span style="color:#ff00ff;">__LINE__</span>)=<span style="color:#008000;">p</span>; <span style="color:#0000ff;">if</span>(<span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">s</span>,<span style="color:#ff00ff;">__LINE__</span>)) <span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">s</span>,<span style="color:#ff00ff;">__LINE__</span>)</pre>
<p>Uff, wreszcie działa. Makro wygląda fatalnie, pewnie ma jakiś trudny do znalezienia błąd, a już na pewno nie jest idiotoodporne, ale przecież nie o to chodzi. Chodzi o zasady i cwaniactwo.</p>
<p>Edit:</p>
<p>Spróbujmy jeszcze naprawić sytuację podaną przez Xiona. Jeśli ktoś spróbuje użyć naszego makra w warunku, albo pętli bez nawiasów, to oczywiście drugi wiersz wypada poza warunkiem i się nie skompiluje ze względu na brak zmiennej w zakresie. Dadawanie nawiasów klamrowych nie rozwiązuje problemu ze względu na wystawianie zmiennej poza makro. Na szczęście poprawka jest bardzo prosta:</p>
<pre style="padding-left:30px;"><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">CONCATENATE</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>) <span style="color:#008000;">x</span>##<span style="color:#008000;">y
</span><span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>) <span style="color:#ff00ff;">CONCATENATE</span>(<span style="color:#008000;">x</span>,<span style="color:#008000;">y</span>)
<span style="color:#0000ff;">#define</span> <span style="color:#ff00ff;">ifNotNull</span>(<span style="color:#008000;">p</span>) <span style="color:#0000ff;">if</span>(<span style="color:#0000ff;">auto</span> *<span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">s</span>,<span style="color:#ff00ff;">__LINE__</span>)=<span style="color:#008000;">p</span>) <span style="color:#ff00ff;">CONCATENATE2</span>(<span style="color:#008000;">s</span>,<span style="color:#ff00ff;">__LINE__</span>)</pre>
<p>Co mądrzejsze narzędzie oczywiście zwróci nam uwagę, że w warunku mamy przypisanie zamiast porównania. Jeszcze jakieś pomysły na zepsucie makra?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/138/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/138/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=138&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2012/02/11/cwaniacki-preprocessor/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Edycja na gorąco</title>
		<link>http://ghurundengine.wordpress.com/2011/12/10/edycja-na-goraco/</link>
		<comments>http://ghurundengine.wordpress.com/2011/12/10/edycja-na-goraco/#comments</comments>
		<pubDate>Sat, 10 Dec 2011 19:37:26 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
		
		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=134</guid>
		<description><![CDATA[Ostatnio uzupełniłem silnik o duży i użyteczny kawałek kodu. Mowa o tytułowej edycji na gorąco, czyli o możliwości podmiany zasobów w czasie działania programu. Sprawa jest dosyć skomplikowana o tyle, że wymaga rozpatrzenia wielu zależności, używania mechanizmów systemowych i uprzedniego przygotowania całego silnika do tego przedsięwzięcia. Przede wszystkim chciałem, żeby podmiana zasobów nie pauzowała całego [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=134&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ostatnio uzupełniłem silnik o duży i użyteczny kawałek kodu. Mowa o tytułowej edycji na gorąco, czyli o możliwości podmiany zasobów w czasie działania programu. Sprawa jest dosyć skomplikowana o tyle, że wymaga rozpatrzenia wielu zależności, używania mechanizmów systemowych i uprzedniego przygotowania całego silnika do tego przedsięwzięcia.<span id="more-134"></span></p>
<p>Przede wszystkim chciałem, żeby podmiana zasobów nie pauzowała całego programu. W momencie, gdy zmieniany jest duży zasób, jego czas ładowania może być znaczący, a wtedy użytkownik zobaczy nieprzyjemną ścinkę. To oznacza, że zasoby powinny być ładowane w tle w oddzielnym wątku. A to z kolei oznacza konieczność synchronizacji. Sam moment przeładowywania zasobu można w głównym wątku obsłużyć np. przez zastąpienie zasobu domyślnym, albo jego pominięcie.</p>
<p>Po drugie wszystkie zasoby są trzymane przez inteligentne wskaźniki. Co prawda ich inteligencja miałaby równe szanse w zawodach z gąbkami, ale swoje zadanie spełniają &#8211; każdy zasób jest ładowany tylko raz. Podmiana wskaźnika w miejscu renderowania nic nie daje, bo poprzednia wersja zasobu jest widoczna, dopóki w programie znajduje się choć jedno odwołanie. To sprawia, że konieczne jest przeładowywanie obecnych zasobów. A to z kolei oznacza, że każdy moduł oprócz uzyskania dostępu do zasobu musi również sprawdzić, czy zasób jest gotowy do użytku.</p>
<p>Trzecia rzecz, to uruchamianie przeładowywania. Moim celem było zautomatuzowanie całego procesu od początku do końca, a więc również wykrywanie modyfikacji dokonywanych w plikach przez programy zewnętrzne. Do tego celu użyłem zdarzeń systemowych pozwalających na wykrycie działań użytkownika na plikach w określonym folderze. Mimo że nazwa &#8216;zdarzenia&#8217; sugeruje informowanie asynchroniczne, trzeba sobie ten mechanizm napisać samemu używając kolejnego wątku. Uff.</p>
<p>Mechanizm edycji zasobów na gorąco wymaga bardzo dokładnego przemyślenia ze względu na liczne problemy, które mogą wystąpić po drodze:</p>
<ul>
<li>Co, jeśli użytkownik w ogóle usunie zasób? W moim przypadku zasób jest ustawiany na nieprawidłowy i czeka w systemie na ponowne wczytanie. Takie zachowanie było najszybsze do napisania ze względu na budowę zasobów w Ghurund. Poza tym pozwala na częściowe działanie większych zasobów, których część zostanie usunięta.</li>
<li>Co, jeśli struktura zasobu zostanie zmieniona na tyle, że logika programu nie będzie w stanie go obsłużyć? Wtedy program powinien przestać działać. Po prostu. Jeśli zmieniamy model gracza tak, że nie ma on już broni, z której może strzelać, to program może albo zabronić strzelania w ogóle, albo strzelać z innego miejsca. Ważne, żeby sprawdzać błedy i starać się odpowiednio reagować. Poza tym część zmian można przewidzieć, np. materiały w Ghurund mają część parametrów zapewnionych automatycznie i zostaną dodane, gdy tylko będą potrzebne.</li>
<li>Co, jeśli od przeładowywanego zasobu zależy inny? To ma miejsce np. w przypadku fizyki, gdzie bryła fizyczna jest generowana z siatki modeu. Tu należałoby stworzyć system powiadomień, ale to przedsięwzięcie jest dosyć duże.</li>
</ul>
<p>Oczywiście należy się zastanowić, na jak dużą ingerencję pozwalamy. Jeśli zmiana będzie naprawdę poważna, program może się też po prostu wywalić. Przecież nie chodzi o to, by gra sprawdzała każdą możliwą sytuację, a użytkownik silnika powinien być tego świadom. Edycja istotnych elementów świata może wymagać zrestartowania całej aplikacji.</p>
<p>Edycja zasobów na gorąco to świetna sprawa i znacznie przyspiesza testowanie zasobów, ale jej poprawne napisanie, to straszny ból. Dokumentacja do funkcji sprawdzania zmian w folderach jest kiepska, synchronizacja utrudnia debugowanie i spowalnia program, a samo wczytywanie nagle staje się bardzo rozdmuchane i trudno się połapać we własnym kodzie.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/134/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/134/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/134/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=134&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/12/10/edycja-na-goraco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Design organiczny, czyli słów kilka o przyjemnych aplikacjach</title>
		<link>http://ghurundengine.wordpress.com/2011/11/10/design-organiczny-czyli-slow-kilka-o-przyjemnych-aplikacjach/</link>
		<comments>http://ghurundengine.wordpress.com/2011/11/10/design-organiczny-czyli-slow-kilka-o-przyjemnych-aplikacjach/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 21:20:39 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
		
		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=120</guid>
		<description><![CDATA[W ostatnią środę miałem okazję wygłosić prezentację dla jakże szanownego grona obiecujących, przyszłych twórców gier i nie tylko. Słowo &#8216;twórcy&#8217; jest tu kluczowe, ponieważ prezentacja nie traktowała o twardym kodowaniu tablic hashujących i innych temu podobnych wspaniałości, a raczej o obecnych trendach w designowaniu wszelkiego oprogramowania. Obecny użytkownik komputera i komórki jest tylko trochę inteligentniejszy [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=120&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>W ostatnią środę miałem okazję wygłosić prezentację dla jakże szanownego grona obiecujących, przyszłych twórców gier i nie tylko. Słowo &#8216;twórcy&#8217; jest tu kluczowe, ponieważ prezentacja nie traktowała o twardym kodowaniu tablic hashujących i innych temu podobnych wspaniałości, a raczej o obecnych trendach w designowaniu wszelkiego oprogramowania.<span id="more-120"></span></p>
<p>Obecny użytkownik komputera i komórki jest tylko trochę inteligentniejszy od krzesła na którym siedzi. Co prawda to założenie jest dosyć odważne, bo oczywiście ludzi inteligentnych jeszcze zupełnie nie zabrakło, ale okazuje się, że i do nich da się zastosować takie podejście. Zacznijmy od początku. Na pewno każdy z nas słyszał o ustawianiu produktów w sklepach, tak, żebyśmy kupili jak najwięcej i jak najdrożej. Albo reklamy. Na jednym obrazku łączy się wybitnie męskiego mężczyznę, małe pieski, drogi zegarek i browar. Po obejrzeniu takiej reklamy w mózgu kobiety podobno pojawia się przekonanie, że facet pijący ten właśnie gatunek piwa jest męski, delikatny, oraz ma kasę i styl.</p>
<p>Pewne podświadome zależności zachodzą w mózgu również podczas używania komórki, internetu, czy komputera. Po pierwsze, jeśli produktu używa się swobodnie, bez zastanawiania się nad przeznaczeniem elementów interfejsu, to automatycznie bardziej doceniamy produkt. Zwłaszcza, że jeśli umiemy używać czegoś bez instrukcji, to czujemy się mądrzejsi i szybko zaczyna się nam to podobać. Z drugiej strony, nawet jeśli najnowsza gra ma fotorealistyczną grafikę, wciągającą fabułę, głęboki dźwięk, a przerywniki filmowe wciskają w fotel, a podczas gry postać cały czas się ślizga po terenie zamiast chodzić, albo ptaki latają po łamanej zamiast po krzywej, to mózg nam podświadomie zgłasza, że coś jest nie tak. Taka gra nigdy nie dostanie najwyższej noty, bo subiektywna ocena, jaką jest przyjemność z grania, wychodzi zbyt niska.</p>
<p style="text-align:center;"><a href="http://ghurundengine.files.wordpress.com/2011/11/c59bniec5bcyca.png"><img class="size-medium wp-image-127 aligncenter" style="border:0 currentColor;margin-top:0;margin-bottom:0;" title="Śnieżyca" src="http://ghurundengine.files.wordpress.com/2011/11/c59bniec5bcyca.png?w=300&#038;h=218" alt="" width="300" height="218" /></a></p>
<p>Teraz, gdy rynek podbijają komórki z ekranem dotykowym, a producenci konsol prześcigają się w tworzeniu różnych kinectów, dążenie do tego, by obsługa produktu była jak najbardziej naturalna, jest jeszcze ważniejsze. Jeśli użytkownik może pociągnąć za listę palcem, to spodziewa się reszty interakcji, którą może spotkać w świecie rzeczywistym, czyli chwytu, rzutu, oraz tarcia i odbicia przy zatrzymywaniu się listy. Do tego dochodzą różnego rodzaju losowe ruchy, drgania, a także szereg efektów graficznych, takich jak cień rzucany przez kontrolkę leżącą nad inną, czy gradient oznaczający wypukłość. Oczywiście to są drobiazgi, ale ich właściwe zastosowanie decyduje o odczuciach użytkownika, a więc o sukcesie produktu i wielkich zyskach ze sprzedaży.</p>
<p>W grach coraz trudniej zauważyć takie braki, ponieważ z coraz szerszym wykorzystaniem silników fizycznych i coraz lepszą grafiką gry po prostu stają się żywe i cały świat jest dobrze rozpoznawalny. Poza tym twórcy gier mogą sobie pozwolić na umieszczenie tutoriala i wyjaśnić wszystkie niejasności. W świecie flashowych reklam i aplikacji mobilnych nie ma tych luksusów. Gry na konsole też zwykle są robione tak, by tutorial był zbędny ze względu na odbiorców.</p>
<p>Na prezentacji można było zobaczyć kilka przykładów dobrego i złego designu, oraz poznać sposoby obsługi użytkownika (tak, tak, to nie użytkownik obsługuje urządzenie, a raczej producent obsługuje użytkownika przy użyciu urządzenia). Jej treść można pobrać <a href="http://ghurundengine.files.wordpress.com/2011/11/marcin-korniluk-design-organiczny.pptx">tutaj</a>.</p>
<p>Swoją drogą ciekawi mnie, ile osób zwróciło uwagę na to, że sama treść prezentacji zawierała kilka elementów sprawiających, że jej odbiór teoretycznie powinien być lepszy. Wygląd był prosty i nie rozpraszał animacjami, czy kolorystyką. Nie było agendy, ani całkowitej ilości slajdów. Animacje były zrobione tak, by odbiorca nie zaczynał czytać reszty slajdu, zamiast słuchać. Screenshoty miały dodany cień i nakładały się w odpowiedni sposób sugerując ważność i nadając pewną wypukłość. Ciekawym takich zagrywek polecam przedmiot Techniki Prezentacji na EiTI.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/120/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/120/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/120/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=120&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/11/10/design-organiczny-czyli-slow-kilka-o-przyjemnych-aplikacjach/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>

		<media:content url="http://ghurundengine.files.wordpress.com/2011/11/c59bniec5bcyca.png?w=300" medium="image">
			<media:title type="html">Śnieżyca</media:title>
		</media:content>
	</item>
		<item>
		<title>Zły kod, użyteczny kod</title>
		<link>http://ghurundengine.wordpress.com/2011/09/17/zly-kod-uzyteczny-kod/</link>
		<comments>http://ghurundengine.wordpress.com/2011/09/17/zly-kod-uzyteczny-kod/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 17:11:43 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
		
		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=116</guid>
		<description><![CDATA[Dawno temu, w czasach, których nikt nie pamięta, słowo kluczowe &#8216;goto&#8217; zostało napiętnowane i zakazane. Powodem takiej nagonki jest artykuł Edsgera Dijkstry &#8216;Go to statement considered harmful&#8217;, w którym naukowiec sprzeciwił się nadmiernemu używaniu instrukcji skoku bezwarunkowego. Jak to zwykle bywa, sprawa została opacznie zrozumiana, a kod z tego powodu cierpi. Goto może być przydatne. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=116&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Dawno temu, w czasach, których nikt nie pamięta, słowo kluczowe &#8216;goto&#8217; zostało napiętnowane i zakazane. Powodem takiej nagonki jest artykuł Edsgera Dijkstry &#8216;Go to statement considered harmful&#8217;, w którym naukowiec sprzeciwił się nadmiernemu używaniu instrukcji skoku bezwarunkowego. Jak to zwykle bywa, sprawa została opacznie zrozumiana, a kod z tego powodu cierpi. Goto może być przydatne. Jak?</p>
<p><span id="more-116"></span></p>
<p>Najpierw oczywiście trzeba się zastanowić, dlaczego goto może być złe. Jak to się mówi ładnie, przyjaciół trzymaj blisko, a wrogów jeszcze bliżej (żeby móc ich powstrzymać, rzecz jasna), a tu przecież mówimy o wymyśle z czeluści piekieł. Narzędziu do tego stopnia  złym, że funkcjonuje w Javie jako słowo kluczowe bez implementacji, tj. jest zastrzeżone, ale nie da się go do niczego użyć.</p>
<p>Przede wszystkim skoki z użyciem goto mogą być znacznie swobodniejsze, niż break/continue, czy zwykłe zakończenie pętli. Dzięki temu możemy wyskoczyć z kilku pętli, czy cofnąć się w wykonaniu programu. To sprawia, że bardzo łatwo przeoczyć istotny fragment kodu i przeskoczyć inicjalizację, bądź deinicjalizację jakiejś zmiennej. Oczywiście to najczęściej powoduje wysypanie się programu, a piekielni twórcy goto śmieją się wtedy z programisty ile mają tchu w płucach.</p>
<p>Druga sprawa, to czytelność kodu. Goto pozwala na swobodne skoki, więc wykonanie programu może nagle pójść zupełnie inaczej. Dla procesora to i tak wszystko jedno, czy skok wykona w wyniku użycia break, czy goto, ale programista czytający kod nagle staje przed niebanalnym zadaniem. Wszystko, czego się nauczył o możliwościach sterowania przepływem programu może wsadzić sobie w&#8230; do śmietnika, bo tu jest wolna amerykanka. Skok nie kończy się na następnej klamrze, w poziomie wyżej, czy w następnej metodzie, ale w dowolnym miejscu kodu oznaczonym etykietą.</p>
<p>Oczywiście puryści i znawcy C++ poprawiliby mnie, jeśli chodzi o zasady działania goto, albo wymienili rzeczy, które dzieją się, lub mogłyby się dziać przy przeskakiwaniu nawiasów klamrowych. Wymieniłem raczej idee, którymi kierują się hejterzy, niż dokładne zasady działania. A teraz do czego goto może być przydatne?</p>
<p>Przede wszystkim do kończenia pętli, najczęściej wielopoziomowych. Ciekawym przykładem jest wykonywanie operacji, jeśli warunek nie zostanie spełniony dla żadnej z iteracji. Poniżej przykład dla jednopoziomowej pętli, która wykonuje operację tylko, jeśli obiekt nie został znaleziony w kolekcji.</p>
<pre><strong><span style="color:#3366ff;">for</span></strong> <strong>(</strong>int i=0; i&lt;list.size; i++<strong>) {</strong>
    <strong><span style="color:#3366ff;">if</span>(</strong>list[i]==value<strong>)</strong>
        <span style="color:#3366ff;"><strong>goto</strong></span> found;
<strong>}</strong>
list.add<strong>(</strong>value<strong>)</strong>;
found:</pre>
<p>Przykład jest banalny i można go obejść na dziesiątki sposobów. Najprostsze dwa to użycie flagi, albo napisanie metody listy do szukania elementu. Jeśli jednak warunek się skomplikuje, użycie goto może być znacznie bardziej przejrzyste i ograniczyć ilość kodu potrzebną do uzyskania właściwego rezultatu. Przykład drugi:</p>
<pre><strong><span style="color:#3366ff;">if</span>(</strong>!initGraphics<strong>(</strong>buffers<strong>))</strong>
    <span style="color:#3366ff;"><strong>goto</strong></span> cleanUp;
<strong><span style="color:#3366ff;">if</span>(</strong>!initInput<strong>(</strong>buffers2<strong>))</strong>
    <span style="color:#3366ff;"><strong>goto</strong></span> cleanUp;
print<strong>(</strong><span style="color:#993300;">"initialization done"</span><strong>)</strong>;
cleanUp:
<span style="color:#3366ff;"><strong>delete</strong></span><strong>[]</strong> buffers;
<strong><span style="color:#3366ff;">delete</span>[]</strong> buffers2;</pre>
<p>Drugi przykład jest wzorowany na przykładach do DirectX. Tam większość inicjalizacji wygląda w ten sposób &#8211; sprzątanie, które jest wykonywane niezależnie od rezultatu wywoływanych metod, jest wykonywane na końcu po etykiecie, do której można skoczyć, gdy wiadomo, że już nie uda się zainicjalizować tego fragmentu aplikacji. Oczywiście można się uprzeć, że i tu da się obejść goto, np. z użyciem RAII. Niemniej jednak okazuje się, że są miejsca, gdzie goto jest użyteczne i można się pokusić o jego użycie. Trzeba tylko pamiętać o zasłonieniu klawiatury i monitora łokciem.</p>
<p>Swoją drogą warto zauważyć ciekawą implikację, która się urodziła po drodze. Goto jest wymysłem i narzędziem piekielnym, a Microsoft go używa. Wiadomo więc, skąd pochodzą.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/116/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=116&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/09/17/zly-kod-uzyteczny-kod/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Jak pisanie silnika przydaje się na systemie z robotem</title>
		<link>http://ghurundengine.wordpress.com/2011/08/30/jak-pisanie-silnika-przydaje-sie-na-systemie-z-robotem/</link>
		<comments>http://ghurundengine.wordpress.com/2011/08/30/jak-pisanie-silnika-przydaje-sie-na-systemie-z-robotem/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 21:28:19 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
		
		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=111</guid>
		<description><![CDATA[Wpis nie jest stricte silnikowy, ale ma pewne przesłanie, nawiązanie i ideę. Tadaa. Otóż ostatnio przyszło mi zaimplementować dosyć zwyczajną rzecz dla silnikologów, a wyjątkowo nietypową dla developerów na pewną platformę z robotem w logo. Buforowanie danych nie jest niczym nowym. Dysk buforuje zapisy i odczyty, procesor ma cache, uczeń trzyma najczęściej używane przybory w plecaku, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=111&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Wpis nie jest stricte silnikowy, ale ma pewne przesłanie, nawiązanie i ideę. Tadaa. Otóż ostatnio przyszło mi zaimplementować dosyć zwyczajną rzecz dla silnikologów, a wyjątkowo nietypową dla developerów na pewną platformę z robotem w logo.</p>
<p><span id="more-111"></span></p>
<p>Buforowanie danych nie jest niczym nowym. Dysk buforuje zapisy i odczyty, procesor ma cache, uczeń trzyma najczęściej używane przybory w plecaku, a zakochany facet ma swoją wybrankę wpisaną pod &#8216;aaaa&#8217;+imię, żeby było ją łatwo wybrać. Generalnie każdy buforuje wszystko, co się tylko da, czasem nieświadom tego ciekawego działania. Pisząc silnik graficzny oczywiście chce się zmieścić jak najwięcej w pamięci karty, a najlepiej w ogóle wszystko w jednej teksturze, czy innym buforze, żeby nie przełączać nawet pojedynczego wskaźnika niepotrzebnie.</p>
<p>Drugą rzeczą oczywistą dla twórców silników jest wstępne przetwarzanie danych. Dane duże przygotowywuje się w zewnętrznym programie, a mniejsze podczas wczytywania. Każdy model ma mieć od razu policzone normalne i styczne, a każda tekstura ma być sparowana z odpowiednią mapą przemieszczeń. Do tego PRT, lightmapy i skompilowane shadery. Podczas wykonywania głównej pętli nie robi się nic niepotrzebnego. Najszybsze operacje, to takie, których nie trzeba wykonać podczas wykonania programu, a więc również te, które udało nam się wykonać wcześniej i zapisać częściowy rezultat.</p>
<p>Jednym z popularniejszych efektów ubocznych obu tych idei jest zrzucanie pamięci GPU na dysk. Taki format danych jest najlepszy, bo jego wczytanie jest banalne, dane nie wymagają przetworzenia przed wykorzystaniem przez kartę graficzną, a przy okazji nikt nam nie grzebie w plikach, bo to w końcu nie xml. Oczywiście przy okazji pojawia się pośrednie buforowanie, tj. w pamięci RAM trzymana jest kopia w razie braku pamięci GPU. Dzięki tej właśnie sprytnej idei zdziałałem ostatnio galerię na wymieniony wcześniej system &#8211; Androida.</p>
<p>Pomysł jest dosyć karkołomny, jeśli chodzi o typowe podejście androidowca. Otóż pamięci na stercie aplikacji jest za mało, żeby trzemać w niej wszystkie obrazki, a wczytywanie podczas działania powoduje poważne opóźnienia, nawet, jeśli wczytujemy w oddzielnym wątku. Większość urządzeń ma znaczną ilość wolnej pamięci RAM, która jest niedostępna z poziomu Javy, ale można ją zaalokować z poziomu biblioteki natywnej i tam trzymać bufor danych, które nie mieszczą się na stercie aplikacji. Widać analogię? Dane trzymane w cache wczytuje się znacznie szybciej, a sam bufor jest na tyle duży, że pomieści kilkukrotnie więcej danych. Wczytujemy do bufora pliki i w ten sposób uzyskujemy superszybki, wielowątkowy system plików.</p>
<p>Dalej oczywiście można dane wstępnie przetworzyć, tak, by przeniesienie interesującego nas fragmentu bufora do pamięci aplikacji było jak najmniej obciążające. W przypadku galerii będą to poszczególne piksele. Zysk jest o tyle widoczny, że obrazki zwykle trzymamy w formie skompresowanej ze względu na rozmiar, a standardowe metody rysujące nie są w stanie posługiwać się bezpośrednio formatem innym niż RGBA8. Szczęśliwie bitmapa trzyma piksele w postaci natywnej, więc przeniesienie danych między pamięcią aplikacji a buforem to kwestia jednego memcpy.</p>
<p>W ten sposób trafiliśmy do domu. Jeśli ktoś się porywa na tworzenie dużych, wybajerzonych aplikacji na urządzenie, które ma 16 MB pamięci, to musi się spodziewać pewnych nieczystych zagrań i kombinacji. A kto się na tym lepiej zna, niż programiści gier?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/111/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/111/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/111/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=111&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/08/30/jak-pisanie-silnika-przydaje-sie-na-systemie-z-robotem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Srutu tutu, model z drutu</title>
		<link>http://ghurundengine.wordpress.com/2011/08/19/srutu-tutu-model-z-drutu/</link>
		<comments>http://ghurundengine.wordpress.com/2011/08/19/srutu-tutu-model-z-drutu/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 00:22:49 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
				<category><![CDATA[Różności]]></category>

		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=106</guid>
		<description><![CDATA[Na modele wireframe nie ma specjalnie dobrej polskiej nazwy, stąd to jakże uroczo sparafrazowane powiedzonko z czasów gimnazjum w tytule. Modele w trybie wireframe mają wyświetlane same krawędzie prymitywów, stąd nazywa się czasem modelami drutowymi. Ich użycie jest banalne i sprowadza się do ustawienia odpowiedniej flagi w użwanej przez nas bibliotece. Ja za to (bardziej [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=106&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Na modele wireframe nie ma specjalnie dobrej polskiej nazwy, stąd to jakże uroczo sparafrazowane powiedzonko z czasów gimnazjum w tytule. Modele w trybie wireframe mają wyświetlane same krawędzie prymitywów, stąd nazywa się czasem modelami drutowymi. Ich użycie jest banalne i sprowadza się do ustawienia odpowiedniej flagi w użwanej przez nas bibliotece. Ja za to (bardziej z przekory, niż potrzeby) napisałem sobie odpowiedniego shaderka. Jak?</p>
<p><span id="more-106"></span></p>
<p>Bardzo prosto. Najważniejszy jest jeden trik. Wartości ustawiane w wierzchołkach są interpolowane przed wejściem do pixel shadera. Jeśli zmienna będzie miała tę samą wartość dla dwóch wierzchołków (np. 1), a inną dla trzeciego wierzchołka (np. 0), to łatwo można stwierdzić, czy rysujemy właśnie piksel należący do odcinka łączącego pierwsze dwa wierzchołki porównując odczytaną wartość z zapisaną dla tych wierzchołków.</p>
<p>Mamy trzy odcinki i do ich oznaczenia możemy wykorzystać trzy składowe jakiegoś wektora przekazywanego do pixel shadera. Wartości dla wierzchołków można wygenerować w locie. Geometry shader dysponuje informacjami o trójkątach, więc bez problemu jest w stanie stworzyć trzy pary i dodać wymagane informacje.</p>
<p>Do sprawdzenia wartości piksela używamy funkcji <em>any(float3)</em>. Jeśli wektor zawiera choć jedną wartość niezerową, zwraca <em>true</em>, tj. właśnie rysujemy krawędź. Oczywiście wartości trzeba sobie odpowiednio sprogować. I pikczer na koniec.</p>
<p><a href="http://ghurundengine.files.wordpress.com/2011/08/wireframe-shader.png"><img class="aligncenter size-full wp-image-107" title="wireframe shader" src="http://ghurundengine.files.wordpress.com/2011/08/wireframe-shader.png?w=630" alt=""   /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/106/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=106&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/08/19/srutu-tutu-model-z-drutu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>

		<media:content url="http://ghurundengine.files.wordpress.com/2011/08/wireframe-shader.png" medium="image">
			<media:title type="html">wireframe shader</media:title>
		</media:content>
	</item>
		<item>
		<title>Przetwarzacze obrazu lekko nie mają</title>
		<link>http://ghurundengine.wordpress.com/2011/07/26/przetwarzacze-obrazu-lekko-nie-maja/</link>
		<comments>http://ghurundengine.wordpress.com/2011/07/26/przetwarzacze-obrazu-lekko-nie-maja/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 23:12:18 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
				<category><![CDATA[Różności]]></category>

		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=98</guid>
		<description><![CDATA[Na wstępie warto by się wytłumaczyć z tytułu. Otóż język polski ma to do siebie, że jeśli jakiegoś wyrazu w nim brakuje, to jego stworzenie bywa dosyć trudne, a na pewno trudniejsze, niż np. w języku angielskim, czy niemieckim (rzeczowniki rox). Chodzi oczywiście o ludzi zajmujących się przetwarzaniem obrazu (2D). A czemu lekko nie mają? [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=98&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Na wstępie warto by się wytłumaczyć z tytułu. Otóż język polski ma to do siebie, że jeśli jakiegoś wyrazu w nim brakuje, to jego stworzenie bywa dosyć trudne, a na pewno trudniejsze, niż np. w języku angielskim, czy niemieckim (rzeczowniki rox). Chodzi oczywiście o ludzi zajmujących się przetwarzaniem obrazu (2D). A czemu lekko nie mają?</p>
<p><span id="more-98"></span></p>
<p>Przetwarzanie obrazu cierpi na szereg ułomności związanych ze złą jakością grafiki źródłowej, teksturami, szumem, czy głębią ostrości. Dla przykładu rozpoznawanie krawędzi postaci ludzkiej ubranej w koszulę w kratę jest zajęciem dla zaawansowanego masochisty mieszkającego za kręgiem polarnym. Otóż wstępnie taki obraz należy przetworzyć (wzmocnić, wyostrzyć, usunąć szum), następnie zastosować algorytm segmentacji świadomy istnienia tekstur, a następnie przetworzyć segmenty na krawędzie obrysu. Większość zastosowanych tu algorytmów może być podstawą pracy magisterskiej.</p>
<p>Przetwarzanie obrazu zajmuje się też mniejszymi krokami, tj. produkcją i zastosowaniem rozmaitych filtrów służących np. do poprawy jakości zdjęć. Obraz można wzmacniać, wyostrzać, rozmywać, zmieniać kontrast i jasność, zmieniać kolory, oraz robić masę ciekawych rzeczy prowadzących do zupełnie nierealistycznych rezultatów. Wszystko to pięknie wygląda w teorii, ale w praktyce mało który filtr daje naprawdę dobre wyniki dla różnych przypadków. Przykładowo wyostrzanie zupełnie nie nadaje się do poprawy ostrości zdjęć zawierających elementy o różnej ostrości. Powód jest bardzo prosty &#8211; przetwarzane obrazy zawierają niewielką ilość informacji. W zasadzie nie wiadomo nic o głębi, granicach między obiektami, elementach zasłoniętych, oświetleniu, położeniu obiektywu, czy scenie. Dokładnie znane są tylko kolory poszczególnych pikseli. Dlatego też można zmienić jasność, ale nie można zmienić oświetlenia. Można wyostrzyć i rozmyć obraz, ale nie można zmienić odległości na którą skupiony jest obiektyw. Można zmienić kolory, ale nie można zmienić właściwości optycznych materiałów. Jednym słowem lipa.</p>
<p style="text-align:center;"><img class="aligncenter" src="http://upload.wikimedia.org/wikipedia/commons/0/01/Lily-M7292-As-shot-and-manual.jpg" alt="" width="481" height="360" /></p>
<p>Dlatego właśnie przetwarzacze lekko nie mają. A kto ma lekko? Oczywiście ten, kto przetwarza obraz, którego jest autorem. Mowa oczywiście o programistach grafiki i efektach przetwarzania końcowego (ang. postprocess) służących do rozmaitych operacji na obrazie generowanym przez wszelkie silniki, frameworki, devkity i inne mądre kawałki kodu. Obraz generowany przez komputer najczęściej jest idealnej jakości w sensie przydatności do przetwarzania. Wszystkie kolory, krawędzie, tekstury, czy jasności są dokładnie takie, jakich życzył sobie autor, a więc nie ma potrzeby wstępnego przygotowania obrazu. Dodatkowo programista dysponuje informacjami o scenie, parametrach światła, głębi, geometrii, teksturach, czy parametrach urządzenia rejestrującego obraz. Dzięki temu zamiast rozpoznawać krawędzie w obrazie wynikowym można to zrobić z użyciem geometrii sceny, albo bufora głębokości. Te informacje są zupełnie niezależne od tekstur i oswietlenia, oraz można z nich usunąć niepotrzebne elementy, więc wynik działania filtru, czy algorytmu jest praktycznie idealny. Koszt takiej operacji jest niższy, niż w przypadku klasycznego przetwarzania obrazu, bo nie trzeba przygotowywać danych, a ich rozdzielczość może być znacznie niższa przy jednakowych, bądź lepszych wynikach. Rzućmy okiem na przykładowy wynik rozpoznawania krawędzi w obrazie z użyciem laplasjanu na buforze głębokości:</p>
<p style="text-align:center;"><a href="http://ghurundengine.files.wordpress.com/2011/07/toon2.png"><img class="aligncenter size-full wp-image-102" title="toon2" src="http://ghurundengine.files.wordpress.com/2011/07/toon2.png?w=630&#038;h=253" alt="" width="630" height="253" /></a></p>
<p>Oczywiście przetwarzanie obrazu komputerowego może być równie dobrze uznane za generowanie, więc tradycyjni przetwarzacze nie powinni się czuć w żaden sposób gorsi (w końcu wyniki ich pracy zwykle wyglądają chałowo). Poza tym niedawno czytałem o aparacie, który zapisuje dodatkowe informacje o scenie, więc być może niedługo tradycyjne przetwarzanie obrazu spotka los dinozaurów.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/98/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/98/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/98/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=98&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/07/26/przetwarzacze-obrazu-lekko-nie-maja/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>

		<media:content url="http://upload.wikimedia.org/wikipedia/commons/0/01/Lily-M7292-As-shot-and-manual.jpg" medium="image" />

		<media:content url="http://ghurundengine.files.wordpress.com/2011/07/toon2.png" medium="image">
			<media:title type="html">toon2</media:title>
		</media:content>
	</item>
		<item>
		<title>Wygładzanie jak nowe</title>
		<link>http://ghurundengine.wordpress.com/2011/07/23/wygladzanie-jak-nowe/</link>
		<comments>http://ghurundengine.wordpress.com/2011/07/23/wygladzanie-jak-nowe/#comments</comments>
		<pubDate>Sat, 23 Jul 2011 02:17:46 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
				<category><![CDATA[Różności]]></category>

		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=91</guid>
		<description><![CDATA[W DirectX 10.1 użytkownicy dostali do dyspozycji dostęp do poszczególnych próbek zapisanych w teksturach z multisamplingiem. Tyle wie każdy poważny koder. Tylko co z tego tak naprawdę wynika? W sieci można znaleźć przykłady pokazujące, w jaki sposób korzystając z ładowania poszczególnych próbek wygenerować ładny, wygładzony obraz. W zasadzie wszystkie sumują w pętli wszystkie próbki i [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=91&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>W DirectX 10.1 użytkownicy dostali do dyspozycji dostęp do poszczególnych próbek zapisanych w teksturach z multisamplingiem. Tyle wie każdy poważny koder. Tylko co z tego tak naprawdę wynika?</p>
<p><span id="more-91"></span></p>
<p>W sieci można znaleźć przykłady pokazujące, w jaki sposób korzystając z ładowania poszczególnych próbek wygenerować ładny, wygładzony obraz. W zasadzie wszystkie sumują w pętli wszystkie próbki i generują wyjście z uśrednionych wartości. Można też iść o krok dalej i policzyć wynikowy kolor per próbka i uśrednić na końcu.</p>
<p>Oczywiście próbki można wykorzystywać w znacznie bardziej kreatywny sposób. Z punktu widzenia programu tekstura z wieloma próbkami na piksel, to tablica tekstur. Próbki indeksuje się z użyciem trzech intów. W związku z tym można taką teksturę wykorzystywać np. do zapisywania kilku warstw obiektów przezroczystych w algorytmie uzyskiwania przezroczystości niezależnej od kolejności obiektów.</p>
<p>Oprócz czytania dowolnej próbki dostajemy możliwość generowania wybranej próbki (SV_SampleIndex), określania położenia próbki w pikselu (GetRenderTargetSamplePosition, GetSamplePosition), czy odczytywania i ustawiania maski pokrycia piksela (SV_Coverage). Część zmiennych jest zapewniana automatycznie wprost w shaderach. Wystarczy zadeklarować dodatkowy parametr, a DirectX uzupełni go odpowiednią wartością.</p>
<p>Te dodatki są o tyle ważne, że w przypadku bardziej złożonych potoków (jak w przypadku metody light pre-pass) istnieją przebiegi multisample -&gt; multisample. Generowanie obrazu metodą uśrednienia próbek powoduje artefakty na krawędziach obiektów w wynikowym obrazie. Poza tym multisampling w przypadku bufora geometrii jest ważny głównie na krawędziach, więc dla pozostałych pikseli można go wyłączyć z użyciem pokrycia zyskując na wydajności.</p>
<p>Shader obliczający oświetlenie per próbka w HLSL wygląda tak:</p>
<pre><span style="color:#0000ff;">float4 </span><span style="color:#993300;">pixelMain</span>(<span style="color:#008080;">Geometry2Pixel</span> <span style="color:#008000;">psIn</span>,<span style="color:#0000ff;">uint </span><span style="color:#008000;">sampleIndex</span> :<span style="color:#0000ff;"> SV_SampleIndex</span>):<span style="color:#0000ff;">SV_Target</span>{ <span style="color:#999999;">// automatyczny parametr włączający renderowanie per próbka</span>
<span style="color:#0000ff;">    float4 </span><span style="color:#008000;">geom</span> = <span style="color:#008000;">geometryBuffer</span>.<span style="color:#993300;">Load</span>(<span style="color:#008000;">psIn.position.xy</span>,<span style="color:#008000;">sampleIndex</span>);

    ... <span style="color:#999999;">// standardowe obliczenia oświetlenia</span>

    <span style="color:#008000;"><span style="color:#0000ff;">return</span> color</span>;
}</pre>
<p>Okazuje się, że w większości przypadków magii nie ma. Trzeba za to mieć świadomość istnienia nowych możliwości i nauczyć się je wykorzystywać. Potem zostaje tylko cieszyć się z ładnie wygładzonego obrazu.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=91&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/07/23/wygladzanie-jak-nowe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Drobne paradoksy projektowe</title>
		<link>http://ghurundengine.wordpress.com/2011/04/22/drobne-paradoksy-projektowe/</link>
		<comments>http://ghurundengine.wordpress.com/2011/04/22/drobne-paradoksy-projektowe/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 19:49:11 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
				<category><![CDATA[Różności]]></category>

		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=84</guid>
		<description><![CDATA[Na pewno każdy programista stanął kiedyś przed tzw. ważną decyzją projektową. Oczywiście zdarzają się i decyzje mniej ważne, oraz zupełnie bez znaczenia. Inżynieria oprogramowania ostrzega &#8211; błędy projektowe są najtrudniejsze do poprawienia, a więc kosztują najwięcej. Na szczęście nie o mój błąd się rozchodzi. Otóż postanowiłem dopisać obsługę ładnego, wygładzonego tekstu. Oczywiście tekst z atlasu, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=84&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Na pewno każdy programista stanął kiedyś przed tzw. ważną decyzją projektową. Oczywiście zdarzają się i decyzje mniej ważne, oraz zupełnie bez znaczenia. Inżynieria oprogramowania ostrzega &#8211; błędy projektowe są najtrudniejsze do poprawienia, a więc kosztują najwięcej. Na szczęście nie o mój błąd się rozchodzi.</p>
<p><span id="more-84"></span></p>
<p>Otóż postanowiłem dopisać obsługę ładnego, wygładzonego tekstu. Oczywiście tekst z atlasu, a atlas z literkami i innymi znakami renderowanymi po trochu przez bardziej złożony mechanizm. Na pierwszy problem natrafiłem przy generacji mip map. Okazuje się, że jest metoda D3D11DeviceContext::GenerateMipmaps(), która generuje wszystkie poziomy na GPU. Wystarczy do tego zadeklarowanie tekstury jako dostępnej do zapisu dla GPU i ustawienie poziomów mipmap na trochę więcej niż 1 (najlepiej na 0). Przy tworzeniu zasobu podajemy deskryptor, dane i wskaźnik do obiektu. Tu zaczyna się problem. Jakie dane? Przecież chcę, żeby to GPU je dla mnie wygenerowało. Jak więc mogę je podać? Metoda tworząca tekstury nie potrafi przyjąć jednego poziomu mip map. Rozwiązań jest kilka, ale wszystkie opierają się na stworzeniu pustej tekstury i uzupełnieniu jej danymi z innego źródła, np. z innej tekstury. Dosyć karkołomne.</p>
<p>Lecimy dalej &#8211; generacja znaków. Użyję WinAPI i narysuję znaki sztuka po sztuce do jakiegoś systemowego bufora. Potem skopiuję je do tekstury. Nawet pasuje, skoro i tak muszę tworzyć teksturę na raty. Znalazłem prostą funkcję, wprost opisaną jako renderującą wygładzony tekst do bitmapy &#8211; idealnie. Okazuje się, że nie może to być dowolna bitmapa, bo tekst zupełnie się nie wygładza. Rysowanie na ekran działa, nie działa natomiast rysowanie do DIBa. Na jednej ze stron MSDN można znaleźć informację, że jest to działanie zamierzone i świadome. Szkoda tylko, że zupełnie nieintuicyjne i nie ma o nim żadnych informacji w dokumentacji. Za to przy opisie na MSDN podane jest obejście tej decyzji projektowej, oraz przyczyna problemu. Chodzi o inną decyzję &#8211; zgodność bitmap. Wygładzanie jest dostępne, ale tylko na bitmapach DDB, czyli w założeniu dedykowanych do jednego konkretnego celu, np. wyświetlania na ekranie, czy drukowania. Ilość stworzonych obiektów potrzebnych do właściwego wyrenderowania jednego znaku tak, by system nie miał mi tego za złe, jest zatrważająca. Na szczęście całość działa.</p>
<p>Na szczęście pisanie silnika równolegle z grą i edytorem ma to do siebie, że błędne decyzje projektowe są zauważane i poprawiane wcześnie, więc o większości z nich użytkownik nawet się nie dowie. Można spać spokojnie.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/84/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=84&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/04/22/drobne-paradoksy-projektowe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
		<item>
		<title>Prawie jak DOD</title>
		<link>http://ghurundengine.wordpress.com/2011/03/30/prawie-jak-dod/</link>
		<comments>http://ghurundengine.wordpress.com/2011/03/30/prawie-jak-dod/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 00:43:32 +0000</pubDate>
		<dc:creator>Zielony</dc:creator>
				<category><![CDATA[Różności]]></category>

		<guid isPermaLink="false">http://ghurundengine.wordpress.com/?p=76</guid>
		<description><![CDATA[Ostatnio miałem okazję uczestniczyć w całkiem ciekawym wykładzie na temat DOD &#8211; Data Oriented Design. Temat znałem już wcześniej, więc zamiast słuchać uważnie, a potem dyskutować, zacząłem kombinować w trochę innym kierunku. DOD stara się walczyć z fanatyzmem obiektowym przez lepsze wykorzystanie i organizację danych zamiast polimorfizmu, dziedziczenia i tym podobnych zabawek z krainy OOP. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=76&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ostatnio miałem okazję uczestniczyć w całkiem ciekawym wykładzie na temat DOD &#8211; Data Oriented Design. Temat znałem już wcześniej, więc zamiast słuchać uważnie, a potem dyskutować, zacząłem kombinować w trochę innym kierunku.</p>
<p><span id="more-76"></span>DOD stara się walczyć z fanatyzmem obiektowym przez lepsze wykorzystanie i organizację danych zamiast polimorfizmu, dziedziczenia i tym podobnych zabawek z krainy OOP. Między innymi projektowanie zorientowane na dane proponuje rozwiązanie popularnego problemu rysowania różnego rodzaju modeli. Zamiast klasycznego napisania metody wirtualnej <em>draw</em> dla każdego rodzaju modelu tworzymy pewne porcje danych, które rysuje się zawsze tak samo. Oszczędzamy więc na skokach przy wołaniu metod wirtualnych, oraz nie musimy pisać dużej ilości klas modeli i metod rysujących.</p>
<p>Zastanówmy się, czy sprawa rzeczywiście wygląda tak różowo. W zasadzie do napisania mamy tyle samo kodu, bo zamiast metody <em>draw</em> mamy metodę <em>generateBuffer</em>, czy coś w ten deseń, a do przechowywania różnych rodzajów modeli nadal wygodnie jest mieć kilka klas. Oczywiście nie warto mieć klasy wroga, czołgu i pocisku, jeśli wszystkie zawierają tylko statyczną siatkę wierzchołków. Mowa raczej o rozróżnieniu na model statyczny, ze szkieletem, cząsteczkowy, itp. Wygląda więc na to, że jedynym dużym zyskiem z przekształcenia metod wirtualnych w dane jest lepsze wykorzystanie cache, predykcji i bufora instrukcji dzięki pozbyciu się skoków do tablic metod wirtualnych.</p>
<p>A czy dałoby się wyeliminować skoki zachowując korzyści płynące ze stosowania metod wirtualnych? Jak to zwykle bywa w takich sytuacjach, odpowiedź brzmi - prawie. Najpierw przypomnijmy sobie pewną interesującą konstrukcję:</p>
<p><code>drawable-&gt;ParticleDrawable::draw();</code></p>
<p>Co w niej jest takiego interesującego? Ano to, że wymusza ona pominięcie skoku do tablicy metod wirtualnych dla metody wirtualnej draw. Oczywiście musimy być pewni typu danego obiektu, więc w tym wypadku nie ma mowy o polimorfiźmie. Rysując obiekty spodziewamy się, że możemy trafić na kilka określonych typów, więc wystarczy zamiast jednej listy z typem ogólnym trzymać kilka list z obiektami określonego typu, oraz wołać metodę rysującą z wymuszeniem typu. To przypomina wyjmowanie specyficznych przypadków przed pętlę i w zasadzie działa bardzo podobnie. Zysk z takiego przekształcenia dla kilku typów i setek wywołań jest oczywisty, a implementacja takiego podejścia zajmuje chwilę.</p>
<p>Pojawia się tylko jedno proste pytanie &#8211; czy nie lepiej zupełnie zrezygnować z metod wirtualnych? Chyba nie, bo wtedy tracimy możliwość obsługi klas dodanych przez użytkownika, czy wymuszania implementacji przez metody abstrakcyjne. Poza tym nie zawsze chcemy zupełnie omijać funkcjonalność metod wirtualnych. Jak np. podczas pisania edytora, który może być odrobinę prostszy z użyciem konstrukcji generycznych.</p>
<p>Oczywiście nie ma tu mowy o rozwiązaniu lepszym, czy gorszym. Ważne, żeby programista znał umiar i pisał tak, by sam się czuł dobrze ze swoim kodem.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ghurundengine.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ghurundengine.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ghurundengine.wordpress.com/76/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ghurundengine.wordpress.com&amp;blog=15688173&amp;post=76&amp;subd=ghurundengine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ghurundengine.wordpress.com/2011/03/30/prawie-jak-dod/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/3d9c05eaa3253bdcf9cca44fe6345412?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">stawonog</media:title>
		</media:content>
	</item>
	</channel>
</rss>
