<?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/"
	>

<channel>
	<title>miku - portfolio &#38; devblog</title>
	<atom:link href="http://www.mi-ku.net/?feed=rss2&#038;langswitch_lang=en" rel="self" type="application/rss+xml" />
	<link>http://www.mi-ku.net</link>
	<description></description>
	<lastBuildDate>Sun, 25 Jul 2010 19:08:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Audio Color Cubes Visualiser + Augmented Reality</title>
		<link>http://www.mi-ku.net/?p=359&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=359&amp;langswitch_lang=en#comments</comments>
		<pubDate>Wed, 03 Mar 2010 03:00:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Flash + ActionScript]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[audio visualization]]></category>
		<category><![CDATA[augmented reality]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[papervision]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=359</guid>
		<description><![CDATA[Yesterday I&#8217;ve made simple audio visualisation with cubes on wonderfl.net (embedded at the end of the post). User athanassiadis said &#8220;really cool effect, would look great in augmented reality&#8220;, and I was thinking why not, even if I was never programming using any ARToolki library before. Having 2 hours, I&#8217;ve downloaded needed libraries, readed one [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I&#8217;ve made simple <a href="http://wonderfl.net/code/fe34fc3b0273916a9500c9f1dd1b8142388223d3">audio visualisation with cubes</a> on wonderfl.net (embedded at the end of the post). User athanassiadis said &#8220;really cool effect, would look great in <a href="http://en.wikipedia.org/wiki/Augmented_reality">augmented reality</a>&#8220;, and I was thinking why not, even if I was never programming using any ARToolki library before. Having 2 hours, I&#8217;ve downloaded needed libraries, readed one example and put visualisation code into life in AR. Results<br />
<img src="http://www.mi-ku.net/projekty/ARVisualiser/ARVisualiser.jpg" alt="Augmented Reality Flash Results"/></p>
<p>Flash:</p>
<p><a href='http://www.mi-ku.net/projekty/ARVisualiser/ARVisualiser.swf' >ARVisualiser</a> &#8211; only hyperlink because I&#8217;ve had weird problems with embedding.</p>
<p>Because of ARToolkit bases on black and white markers, I&#8217;ve used one of predefined:<br />
<img src="http://www.mi-ku.net/projekty/ARVisualiser/marker.png" alt="AR marker"/><br />
So if You want to try given swf You have to print this marker or draw it on some white paper.</p>
<p>And this is standard wersion on wonderfl:</p>
<div style="text-align:center;width:465px;"><iframe title="Audio Color Cubes Visualiser - wonderfl build flash online" scrolling="no" src="http://wonderfl.net/blogparts/fe34fc3b0273916a9500c9f1dd1b8142388223d3" width="465" height="490" style="border:1px black solid;"></iframe><a href="http://wonderfl.net/code/fe34fc3b0273916a9500c9f1dd1b8142388223d3" title="Audio Color Cubes Visualiser - wonderfl build flash online">Audio Color Cubes Visualiser &#8211; wonderfl build flash online</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=359&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blob on wonderfl.net</title>
		<link>http://www.mi-ku.net/?p=352&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=352&amp;langswitch_lang=en#comments</comments>
		<pubDate>Mon, 01 Mar 2010 02:00:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Flash + ActionScript]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[papervision]]></category>
		<category><![CDATA[wonderfl]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=352</guid>
		<description><![CDATA[
Results after quick codding in ActionScript and Papervision 3D at www.wonderfl.com:

Sphere modifier &#8211; wonderfl build flash online
I like the idea of wonderfl.net website, we quickly can develop some experimental things using popular libraries without installing any IDE and SDK&#8217;s. There is also code ranking. I&#8217;m recommending to check this out :)
]]></description>
			<content:encoded><![CDATA[<p><span id="more-352"></span></p>
<p>Results after quick codding in ActionScript and Papervision 3D at <a href="http://www.wonderfl.com">www.wonderfl.com</a>:</p>
<p><!--more--></p>
<div style="text-align:center;width:465px;"><iframe title="Sphere modifier - wonderfl build flash online" scrolling="no" src="http://wonderfl.net/blogparts/88f593ed2e35c7fcd72405389a9851077ea10f42" width="465" height="490" style="border:1px black solid;"></iframe><a href="http://wonderfl.net/code/88f593ed2e35c7fcd72405389a9851077ea10f42" title="Sphere modifier - wonderfl build flash online">Sphere modifier &#8211; wonderfl build flash online</a></div>
<p>I like the idea of wonderfl.net website, we quickly can develop some experimental things using popular libraries without installing any IDE and SDK&#8217;s. There is also code ranking. I&#8217;m recommending to check this out :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=352&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Project: DEPTH 01</title>
		<link>http://www.mi-ku.net/?p=342&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=342&amp;langswitch_lang=en#comments</comments>
		<pubDate>Thu, 25 Feb 2010 02:46:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Flash + ActionScript]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[papervision]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=342&amp;langswitch_lang=en</guid>
		<description><![CDATA[Ostatnio podróże pociągiem wykorzystuję na kodowanie w ActionScript eksperymentalnej gierki o nazwie &#8220;DEPTH 01&#8243;. Na podstronie projektu znajdzuje się mini blog z postępów prac, a tutaj napiszę więcej jak już projekt przybierze jakąś konkretną formę.
Podstrona projektu: http://depth.mi-ku.net
Jeżeli ktoś będzie miał jakieś ciekawe idee na rozwinięcie pomysłu to jestem otwarty na propozycje.
]]></description>
			<content:encoded><![CDATA[<p>Ostatnio podróże pociągiem wykorzystuję na kodowanie w ActionScript eksperymentalnej gierki o nazwie &#8220;DEPTH 01&#8243;. Na podstronie projektu znajdzuje się mini blog z postępów prac, a tutaj napiszę więcej jak już projekt przybierze jakąś konkretną formę.</p>
<p>Podstrona projektu: <a href="http://depth.mi-ku.net">http://depth.mi-ku.net</a></p>
<p>Jeżeli ktoś będzie miał jakieś ciekawe idee na rozwinięcie pomysłu to jestem otwarty na propozycje.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=342&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SpringBall</title>
		<link>http://www.mi-ku.net/?p=331&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=331&amp;langswitch_lang=en#comments</comments>
		<pubDate>Sat, 06 Feb 2010 23:02:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Flash + ActionScript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=331&amp;langswitch_lang=en</guid>
		<description><![CDATA[W celach nauki Flasha i ActionScript&#8217;a stworzyłem prostą mini grę w dwie godziny, w której zieloną kulką trzeba zbić 20 czerwonych w jak najkrótszym czasie.
Sterowanie:
Przeciąganie niebieskiej kulki za pomocą lewego przycisku myszy.
AC_FL_RunContent = 0;


	if (AC_FL_RunContent == 0) {
		alert("This page requires AC_RunActiveContent.js.");
	} else {
		AC_FL_RunContent(
			'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
			'width', '400',
			'height', '400',
			'src', '/projekty/springball/SpringBall',
			'quality', 'high',
			'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
			'align', 'middle',
			'play', 'true',
			'loop', 'true',
			'scale', 'showall',
			'wmode', 'window',
			'devicefont', 'false',
			'id', [...]]]></description>
			<content:encoded><![CDATA[<p>W celach nauki Flasha i ActionScript&#8217;a stworzyłem prostą mini grę w dwie godziny, w której zieloną kulką trzeba zbić 20 czerwonych w jak najkrótszym czasie.</p>
<p>Sterowanie:<br />
Przeciąganie niebieskiej kulki za pomocą lewego przycisku myszy.<br />
<script language="javascript">AC_FL_RunContent = 0;</script><script src="/projekty/springball/AC_RunActiveContent.js" language="javascript"></script>
<div style="border: 1px solid gray; float: left;">
<script language="javascript">
	if (AC_FL_RunContent == 0) {
		alert("This page requires AC_RunActiveContent.js.");
	} else {
		AC_FL_RunContent(
			'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
			'width', '400',
			'height', '400',
			'src', '/projekty/springball/SpringBall',
			'quality', 'high',
			'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
			'align', 'middle',
			'play', 'true',
			'loop', 'true',
			'scale', 'showall',
			'wmode', 'window',
			'devicefont', 'false',
			'id', 'SpringBall',
			'bgcolor', '#ffffff',
			'name', 'SpringBall',
			'menu', 'true',
			'allowFullScreen', 'false',
			'allowScriptAccess','sameDomain',
			'movie', '/projekty/springball/SpringBall',
			'salign', ''
			); //end AC code
	}
</script><noscript><br />
	<object<br />
	classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="400" height="400" id="SpringBall" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value="SpringBall.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="/projekty/springball/SpringBall.swf" quality="high" bgcolor="#ffffff" width="400" height="400" name="SpringBall" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /><br />
	</object></noscript>
</div>
<div style="clear:both;">
<p>Miałem napisać o projekcie z delfinem w roli głównej, ale zrobię to później, wspomnę tylko, że to projekt do pracy inżynierskiej.</p>
<p>EDIT: Po nauce rysowania w buforze dodałem smugę za kulkami (dla odmiany teraz są dwie zielone)
</p></div>
<p><script language="javascript">AC_FL_RunContent = 0;</script><script src="/projekty/springball/AC_RunActiveContent.js" language="javascript"></script>
<div style="border: 1px solid gray; float: left;">
<script language="javascript">
	if (AC_FL_RunContent == 0) {
		alert("This page requires AC_RunActiveContent.js.");
	} else {
		AC_FL_RunContent(
			'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
			'width', '400',
			'height', '400',
			'src', '/projekty/springball/SpringBall2',
			'quality', 'high',
			'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
			'align', 'middle',
			'play', 'true',
			'loop', 'true',
			'scale', 'showall',
			'wmode', 'window',
			'devicefont', 'false',
			'id', 'SpringBall',
			'bgcolor', '#ffffff',
			'name', 'SpringBall2',
			'menu', 'true',
			'allowFullScreen', 'false',
			'allowScriptAccess','sameDomain',
			'movie', '/projekty/springball/SpringBall2',
			'salign', ''
			); //end AC code
	}
</script><noscript><br />
	<object<br />
	classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="400" height="400" id="SpringBall" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value="/projekty/springball/SpringBall2.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="/projekty/springball/SpringBall2.swf" quality="high" bgcolor="#ffffff" width="400" height="400" name="SpringBall" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /><br />
	</object></noscript>
</div>
<div style="clear:both;">
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=331&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Porównanie metody Eulera oraz RK4 do integracji równań fizycznych</title>
		<link>http://www.mi-ku.net/?p=326&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=326&amp;langswitch_lang=en#comments</comments>
		<pubDate>Sun, 17 Jan 2010 22:36:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sense framework]]></category>
		<category><![CDATA[physics]]></category>
		<category><![CDATA[RK4]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=326</guid>
		<description><![CDATA[Swego czasu, tak jak opisywałem wcześniej na blogu implementowałem symulację materiału reprezentowanego przez ciała posiadające jedynie masę połączone sprężynami. Wynik był średnio zadowalający gdyż przy mocnym napięciu sprężyn materiał potrafił „eksplodować”, rezultat ten był spowodowany zastosowaniem „zwykłego” integratora Eulera, czyli inaczej mówiąc wzorów fizycznych pamiętanych ze szkoły średniej. Jako, że nie chciałem żeby materiał zachowywał [...]]]></description>
			<content:encoded><![CDATA[<p>Swego czasu, tak jak opisywałem wcześniej na blogu implementowałem symulację materiału reprezentowanego przez ciała posiadające jedynie masę połączone sprężynami. Wynik był średnio zadowalający gdyż przy mocnym napięciu sprężyn materiał potrafił „eksplodować”, rezultat ten był spowodowany zastosowaniem „zwykłego” integratora Eulera, czyli inaczej mówiąc wzorów fizycznych pamiętanych ze szkoły średniej. Jako, że nie chciałem żeby materiał zachowywał się jak guma zacząłem poszukiwania rozwiązania tego problemu i natknąłem się na metodę Runge-Kutty rzędu czwartego, dodatkowo pokryło to się jakoś z zajęciami na uczelni na których omawialiśmy RK4 jak i inne metody. Ostatecznie zaimplementowałem ten algorytm posiłkując się tym artykułem: <a href="http://gafferongames.com/game-physics/integration-basics/">http://gafferongames.com/game-physics/integration-basics/</a><br />
Wynik jest naprawdę dobry, można napiąć sprężyny bardzo mocno przez co już nie zachowuje się jak guma.<br />
A jako, że ostatnio mieliśmy przygotować referat na zajęcia z Fizyki to ustaliłem z prowadzącym że zaprezentuję ten temat, bo już miałem z tym doświadczenia i pełną implementację. Na potrzeby prezentacji napisałem małe demko w którym można porównać zachowanie materiału z integratorem Eulera oraz RK4</p>
<p>Rezultat:<br />
<object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/P7EG9zmYTBI&#038;hl=pl_PL&#038;fs=1&#038;color1=0x2b405b&#038;color2=0x6b8ab6"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/P7EG9zmYTBI&#038;hl=pl_PL&#038;fs=1&#038;color1=0x2b405b&#038;color2=0x6b8ab6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p>Do pobrania:</p>
<ul>
<li><a href="http://www.mi-ku.net/projekty/sense/demos/ClothPhysicsDemo01.zip">http://www.mi-ku.net/projekty/sense/demos/ClothPhysicsDemo01.zip</a></li>
</ul>
<p>Żeby nie referat to pewnie powróciłbym do tego tematu później, bo w między czasie (teraz a początek semestru) zacząłem robić mini demko symulacji materiału kolidującego z dowolnymi złożonymi siatkami, aktualnie już działa, ale na CPU jest strasznie wolne i przeniosę implementację na GPU – a dokładnie OpenCL a dodatkowo chcę zrobić coś na wzór demka scenowego więc muszę jakoś to poskładać ładnie.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=326&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sense: Skinning</title>
		<link>http://www.mi-ku.net/?p=320&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=320&amp;langswitch_lang=en#comments</comments>
		<pubDate>Tue, 22 Dec 2009 00:09:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[sense framework]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[Sense]]></category>
		<category><![CDATA[skeletal animiation]]></category>
		<category><![CDATA[skinning]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=320&amp;langswitch_lang=en</guid>
		<description><![CDATA[W ramach projektu o którym niebawem napiszę zaimplementowałem do Sense algorytm skinningu. Aktualnie implementacja nie jest uniwersalna, ale do tego projektu wystarczy, tym bardziej, że skinning teraz wykorzystuje &#8220;kości&#8221; zrobione ze sprężyn :). Rezultat poniżej:


Więcej informacji o projekcie wkrótce, a jakby ktoś w komentarzu napisał żę informacja o algorytmie też by była fajna (ew. ktoś [...]]]></description>
			<content:encoded><![CDATA[<p>W ramach projektu o którym niebawem napiszę zaimplementowałem do Sense algorytm skinningu. Aktualnie implementacja nie jest uniwersalna, ale do tego projektu wystarczy, tym bardziej, że skinning teraz wykorzystuje &#8220;kości&#8221; zrobione ze sprężyn :). Rezultat poniżej:</p>
<p><img src="http://www.mi-ku.net/projekty/sense/images/skinning01.jpg" alt="Skinning algorithm presentation" /></p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/HXkcXWNi7l8&#038;hl=pl_PL&#038;fs=1&#038;color1=0x006699&#038;color2=0x54abd6"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/HXkcXWNi7l8&#038;hl=pl_PL&#038;fs=1&#038;color1=0x006699&#038;color2=0x54abd6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p>Więcej informacji o projekcie wkrótce, a jakby ktoś w komentarzu napisał żę informacja o algorytmie też by była fajna (ew. ktoś ma problem z implementacją itp.) to opiszę.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=320&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wstępna implementacja GUI 3D z wykorzystaniem Stencil bufora</title>
		<link>http://www.mi-ku.net/?p=276&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=276&amp;langswitch_lang=en#comments</comments>
		<pubDate>Sun, 08 Nov 2009 02:10:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[sense framework]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[interactivity]]></category>
		<category><![CDATA[Sense]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=276</guid>
		<description><![CDATA[W tym wpisie chcę się podzielić sposobem implementacji podwalin GUI 3D w swoim frameworku &#8220;Sense&#8221; przy wykorzystaniu bufora Stencil. Wpis jest prawie artykułem i być może po rozwinięciu tematu taki kiedyś powstanie. Adresatami są osoby zainteresowane tzw. &#8220;silnikologią&#8221;, czyli pisaniem własnych silników do gier, jednocześnie mające doświadczenie w programowaniu i zaznajomione przynajmniej w minimalnym stopniu [...]]]></description>
			<content:encoded><![CDATA[<p>W tym wpisie chcę się podzielić sposobem implementacji podwalin GUI 3D w swoim frameworku &#8220;Sense&#8221; przy wykorzystaniu bufora Stencil. Wpis jest prawie artykułem i być może po rozwinięciu tematu taki kiedyś powstanie. Adresatami są osoby zainteresowane tzw. &#8220;silnikologią&#8221;, czyli pisaniem własnych silników do gier, jednocześnie mające doświadczenie w programowaniu i zaznajomione przynajmniej w minimalnym stopniu z jakimś API graficznym. Pierwsza część wpisu omawia sposób opakowania zdarzeń w system menadżera i jego słuchaczy. Ci co mają taką warstwę abstrakcji już zaimplementowaną (lub po prostu mają ją &#8220;gdzieś&#8221; :) ) powinni przejść do części opisującej sam system rozpoznawania obiektów pod myszą i przesyłania im zdarzeń.<br />
<span id="more-276"></span><br />
Od razu zaznaczam, że będzie dużo kodu opakowującego wszystko w obiekty, ale też wspomnę, że w tym wpisie nie opiszę jak zainicjować stencil, jest to w dużej mierze zależne od używanego API graficznego. W związku z tym polecam szukać tych informacji w dokumentacji danego API / biblioteki, jednak jeżeli ktoś będzie miał z tym problem to postaram się odpowiedzieć :). Dodam tylko, że potrzebny jest nam bufor przynajmniej o ośmio-bitowej głębi &#8211; przy której będziemy w stanie obsłużyć 255 elementów GUI.</p>
<h3>Wynik</h3>
<p>Zanim jeszcze przejdę do rzeczy pokażę co zaimplementowałem na kodzie który w około 90% pokrywa się z tym opisanym tutaj. Otóż napisałem sobie kontrolkę która w założeniu ma służyć do przemieszczania, obracania i skalowania obiektów w edytorze, który sobię koduję na boku.</p>
<p>Oto rezultat:</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/zrUUbZU0IHk&#038;hl=pl&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/zrUUbZU0IHk&#038;hl=pl&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
<p><img src="http://www.mi-ku.net/projekty/sense/images/Sense3DGUISample.gif" alt="3D GUI sample control in Sense framework" /></p>
<h3>Do pobrania:</h3>
<p><a href="http://www.mi-ku.net/projekty/sense/demos/Sense3DGUISample.zip">http://www.mi-ku.net/projekty/sense/demos/Sense3DGUISample.zip</a></p>
<p>Do implementacji GUI 3D jest nam potrzebne połączenie wejścia (klawiatura + mysz) z elementami graficznymi które znajdują się w przestrzeni trójwymiarowej. Aby kierować zdarzenia z wejść do obiektów z reprezentacją graficzną potrzebny jest nam jakiś nadrzędny byt, który stwierdzi, że akurat ten obiekt powinien otrzymywać zdarzenia. Już na początku mamy pewien problem związany z tym, że pozycje zdarzeń myszy (kliknięcia i ruch) otrzymujemy w przestrzeni dwuwymiarowej a reprezentacja obiektów trzymamy w przestrzeni trójwymiarowej. W związku z tym potrzebna jest nam technika rozpoznania jaki obiekt znajduje się na danej pozycji bufora 2d obrazu. Często stosowanymi technikami są: </p>
<ul>
<li>użycie pomocniczego bufora obrazu</li>
<li>kolizje promienia utworzonego na podstawie pozycji 2D myszy z obiektami na scenie</li>
</ul>
<p>Ja wybrałem użycie bufora pomocniczego, w nadziei, że będzie szybsze niż sprawdzanie kolizji siatek 3D z promieniem. No i ten sposób wydaje mi się łatwiejszy w implementacji.</p>
<p>Jak stencil nam pomoże w stwierdzeniu jaki obiekt znajduje się na danej pozycji w 2D? Otóż zastosujemy klasyczną technikę, renderowania każdego obiektu z innym indeksem (wartością którą może przechowywać stencil), a w obsłudze zdarzeń myszy stwierdzimy który element jest aktywny przez odczytywanie wartości bufora na danej pozycji myszy. W skrócie pętla renderingu wygląda tak:</p>
<ol>
<li>Czyszczenie bufora obrazu, głębi oraz stencila</li>
<li>Renderowanie wszystkich elementów GUI do stencila</li>
<li>Renderowanie wszystkich elementów GUI do właściwego bufora obrazu</li>
</ol>
<p>W większości przypadków chyba oba kroki można połączyć i rysować od razu do stencila i własciwego bufora obrazu.</p>
<p>A w obsłudze zdarzeń myszy:</p>
<ol>
<li>Ustal pozycje myszy.</li>
<li>Pobierz wartość bufora stencil na danej pozycji myszy.</li>
<li>Jeżeli pobrana wartość równa się wartości początkowej (np. 0) odrzuć zdarzenie.
<li>Znajdź element GUI który odpowiada danej wartości bufora.</li>
<li>Wyślij zdarzenie myszy do znalezionego elementu.</li>
</ol>
<h3>Menedżer zdarzeń</h3>
<p>Na wstępie implementacji jest nam potrzebny jakiś menedżer zdarzeń klawiatury i myszy. W przypadku kiedy w używanym przez nas API mamy dostęp do zdarzeń &#8220;niskopoziomowo&#8221; (np. procedura obsługi okna) to opakujmy wszystko w klasy takie jak InputManager wraz ze słuchaczami dziedziczącymi po KeyboardEventListener i MouseEventListener. Przykład implementacji:</p>
<div class="codesnip-container" >
<div class="codesnip">template&lt; class T &gt; class EventListenerCollector<br />
<span class="br0">&#123;</span><br />
protected:<br />
&nbsp; &nbsp; <span class="kw4">typedef</span> std::<span class="me2">vector</span>&lt; T* &gt; ListenerList;<br />
&nbsp; &nbsp; ListenerList Listeners;<br />
public:<br />
&nbsp; &nbsp; <span class="kw4">void</span> AddEventListener<span class="br0">&#40;</span> T* _Listener <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Listeners.<span class="me1">push_back</span><span class="br0">&#40;</span> _Listener <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ListenerAdded<span class="br0">&#40;</span> _Listener <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> RemoveEventListener<span class="br0">&#40;</span> T* _Listener <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ListenerList::<span class="me2">iterator</span> FindResultIterator = std::<span class="me2">find</span><span class="br0">&#40;</span> Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, _Listener <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> FindResultIterator == Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="kw1">return</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Listeners.<span class="me1">erase</span><span class="br0">&#40;</span> FindResultIterator <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ListenerRemoved<span class="br0">&#40;</span> _Listener <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> RemoveAllListeners<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Listeners.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> ListenerAdded<span class="br0">&#40;</span> T* _Listener <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> ListenerRemoved<span class="br0">&#40;</span> T* _Listener <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span></p>
<p><span class="br0">&#125;</span>;</p>
<p>class InputManager : <br />
&nbsp; &nbsp; public EventListenerCollector&lt; KeyboardEventListener &gt;, <br />
&nbsp; &nbsp; public EventListenerCollector&lt; MouseEventListener &gt;, <br />
<span class="br0">&#123;</span><br />
public:<br />
&nbsp; &nbsp; <span class="kw4">void</span> KeyDown<span class="br0">&#40;</span> KeyboardEventKeyDown &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> KeyUp<span class="br0">&#40;</span> KeyboardEventKeyUp &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> MouseMoved<span class="br0">&#40;</span> MouseEventMove &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> MouseButtonUp<span class="br0">&#40;</span> MouseEventButtonUp &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> MouseButtonDown<span class="br0">&#40;</span> MouseEventButtonDown &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> MouseButtonClick<span class="br0">&#40;</span> MouseEventButtonClick &amp;E <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">void</span> AddKeyboardEventListener<span class="br0">&#40;</span> KeyboardEventListener* <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> RemoveKeyboardEventListener<span class="br0">&#40;</span> KeyboardEventListener* <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">void</span> AddMouseEventListener<span class="br0">&#40;</span> MouseEventListener * <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">void</span> RemoveMouseEventListener<span class="br0">&#40;</span> MouseEventListener * <span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</div>
</div>
<p>Żeby nie utrudniać czytania implementacje metod klasy InputManager pominąłem, ale w zasadzie są dosyć oczywiste. Pierwsze sześć metod zajmuje się przekazywaniem konkretnych struktur zdarzeń do słuchaczy. Kolejne metody Add/Remove nie robią nic innego jak dodają/usuwają kolejnych słuchaczy z kolekcji EventListenerCollector< KeyboardEventListener >::Listeners oraz EventListenerCollector< MouseEventListener >::Listeners.</p>
<p>Podpięcie takiego managera do obsługi zdarzeń z okna może wyglądać następująco:</p>
<div class="codesnip-container" >
<div class="codesnip">&#8230;<br />
<span class="me1">InputManager</span> *IM = &#8230;<br />
<span class="kw1">switch</span><span class="br0">&#40;</span> Message <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
<span class="kw1">case</span> WM_KEYDOWN:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; KeyboardEventKeyDown E<span class="br0">&#40;</span> WW, static_cast&lt; KeyboardEventKeyDown::<span class="me2">VirtualKeyCodeType</span> &gt;<span class="br0">&#40;</span> WParam <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IM-&gt;KeyDown<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> WM_KEYUP:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; KeyboardEventKeyUp E<span class="br0">&#40;</span> WW, static_cast&lt; KeyboardEventKeyUp::<span class="me2">VirtualKeyCodeType</span> &gt;<span class="br0">&#40;</span> WParam <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IM-&gt;KeyUp<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> WM_MOUSEMOVE:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MouseEventMove E<span class="br0">&#40;</span> WW, static_cast&lt; MouseEventMove::<span class="me2">CoordinateType</span> &gt;<span class="br0">&#40;</span> LOWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span> <span class="br0">&#41;</span>, static_cast&lt; MouseEventMove::<span class="me2">CoordinateType</span> &gt;<span class="br0">&#40;</span> HIWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IM-&gt;MouseMoved<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> WM_LBUTTONDBLCLK:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MouseEventButtonClick E<span class="br0">&#40;</span> WW, Sense::<span class="me2">BUTTON_LEFT</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IM-&gt;MouseButtonClick<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> WM_LBUTTONDOWN:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MouseEventButtonDown E<span class="br0">&#40;</span> WW, Sense::<span class="me2">BUTTON_LEFT</span>, LOWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span>, HIWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IM-&gt;MouseButtonDown<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> WM_LBUTTONUP:<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MouseEventButtonUp E<span class="br0">&#40;</span> WW, Sense::<span class="me2">BUTTON_LEFT</span>, LOWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span>, HIWORD<span class="br0">&#40;</span> LParam <span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; WW-&gt;MouseButtonUp<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p><span class="co1">// etc. dla kolejnych eventów</span><br />
&#8230;<br />
<span class="br0">&#125;</span></div>
</div>
<p>Mamy już klasę tworzącą warstwę pomiędzy zdarzeniami z obsługi okna oraz obiekt do dalszego ich rozsyłania. Stworzenie tej warstwy umożliwia również implementacje obsługi zdarzeń z innych źródeł na innych platformach niż Windows, czy też chociażby na zaimplementowanie sprawdzania asynchronicznego stanu urządzeń wejściowych.</p>
<h3>Rozdzielanie zdarzeń do elementów GUI 3D</h3>
<p>Teraz czas na implementacje obiektu, który będzie zarządzał zdarzeniami w ramach obiektów z reprezentacją w przestrzeni trójwymiarowej. Zastanówmy się co jest nam potrzebne. Tak jak wspomniałem obiekty powinny się renderować oprócz do bufora obrazu to i do stencila. Musimy posiadać jakiś mechanizm który powie tym obiektom z jaką wartością stencila mają się renderować. Stwórzmy klasę którą nazwiemy np. StencilInputEventDispatcher która będzie mogła przechowywać wskaźniki do swoich słuchaczy (prawie identycznie jak w przypadku InputManager ) jednak dodatkowo do klasy słuchacza dodamy metody ustawiające wartość stencila oraz odczytujące ustawioną wartość (Set/GetIndex). Przydadzą się jeszcze metody MouseOver i MouseOut, dla oświadczenia danemu słuchaczowi (czyli obiektowi 3D), że najechaliśmy na niego myszą lub też z niego &#8220;zjechaliśmy&#8221;. Od klasy StencilInputEventDispatcher oczekujemy również, że będzie przesyłać zdarzenia wtedy gdy &#8220;zjedziemy&#8221; myszą z obiektu z wciśniętym przyciskiem myszy.</p>
<p>Przykład imlpementacji:</p>
<div class="codesnip-container" >
<div class="codesnip">class StencilInputEventListener<br />
<span class="br0">&#123;</span><br />
public:<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseMoved <span class="br0">&#40;</span> MouseEventMove &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonUp <span class="br0">&#40;</span> MouseEventButtonUp &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonDown <span class="br0">&#40;</span> MouseEventButtonDown &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonClick <span class="br0">&#40;</span> MouseEventButtonClick &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> KeyDown <span class="br0">&#40;</span> KeyboardEventKeyDown &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> KeyUp <span class="br0">&#40;</span> KeyboardEventKeyUp &amp;E <span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseOver <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseOut <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; virtual <span class="kw4">int</span>&nbsp; GetIndex <span class="br0">&#40;</span><span class="br0">&#41;</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> SetIndex&nbsp; <span class="br0">&#40;</span> <span class="kw4">int</span> <span class="br0">&#41;</span> = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span>;<br />
template &lt; typename T &gt;<br />
class ValuePool<br />
<span class="br0">&#123;</span><br />
public:<br />
&nbsp; &nbsp; bool Release<span class="br0">&#40;</span> T Value <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ValueList::<span class="me2">iterator</span> It = std::<span class="me2">find</span><span class="br0">&#40;</span> Values.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Values.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Value <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> It != Values.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Values.<span class="me1">erase</span><span class="br0">&#40;</span> It <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> Reserve<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ValueList::<span class="me2">iterator</span> It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> Value = <span class="nu0">0</span>; <span class="co1">// 0 is reserved</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// TODO: search optimization</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; It = std::<span class="me2">find</span><span class="br0">&#40;</span> Values.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Values.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Value + <span class="nu0">1</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++Value;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">while</span> <span class="br0">&#40;</span> It != Values.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; Values.<span class="me1">push_back</span><span class="br0">&#40;</span> Value <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> Value;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <br />
private:<br />
&nbsp; &nbsp; <span class="kw4">typedef</span> std::<span class="me2">vector</span>&lt; T &gt; ValueList;<br />
&nbsp; &nbsp; ValueList Values;<br />
<span class="br0">&#125;</span>;</p>
<p>class StencilInputEventDispatcher : public MouseEventListener, public KeyboardEventListener, public EventListenerCollector&lt; StencilInputEventListener &gt;<br />
<span class="br0">&#123;</span><br />
public:<br />
&nbsp; &nbsp; StencilInputEventDispatcher<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; virtual <span class="kw4">void</span> ListenerAdded <span class="br0">&#40;</span> StencilInputEventListener* _Listnerer <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> ListenerRemoved <span class="br0">&#40;</span> StencilInputEventListener* _Listnerer <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseMoved <span class="br0">&#40;</span> MouseEventMove &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonUp <span class="br0">&#40;</span> MouseEventButtonUp &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonDown <span class="br0">&#40;</span> MouseEventButtonDown &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> MouseButtonClick <span class="br0">&#40;</span> MouseEventButtonClick &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> KeyDown <span class="br0">&#40;</span> KeyboardEventKeyDown &amp;E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> KeyUp <span class="br0">&#40;</span> KeyboardEventKeyUp &amp;E <span class="br0">&#41;</span>;</p>
<p>private:<br />
&nbsp; &nbsp; ValuePool&lt; <span class="kw4">unsigned</span> <span class="kw4">short</span> &gt; IndexPool;<br />
&nbsp; &nbsp; <span class="kw4">void</span> DetectListeningIndex<span class="br0">&#40;</span> MouseEventMove &amp;E <span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> MouseMovedListeningIndex;<br />
&nbsp; &nbsp; bool LeftDown, RightDown, MiddleDown;<br />
&nbsp; &nbsp; StencilInputEventListener *MouseOverListener;<br />
<span class="br0">&#125;</span>;</p>
<p>
StencilInputEventDispatcher::<span class="me2">StencilInputEventDispatcher</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; : MouseMovedListeningIndex<span class="br0">&#40;</span> -<span class="nu0">1</span> <span class="br0">&#41;</span>, LeftDown<span class="br0">&#40;</span> <span class="kw2">false</span> <span class="br0">&#41;</span>, RightDown<span class="br0">&#40;</span> <span class="kw2">false</span> <span class="br0">&#41;</span>, MiddleDown<span class="br0">&#40;</span> <span class="kw2">false</span> <span class="br0">&#41;</span>, MouseOverListener<span class="br0">&#40;</span> <span class="kw2">NULL</span> <span class="br0">&#41;</span></p>
<p><span class="br0">&#123;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">ListenerAdded</span><span class="br0">&#40;</span> StencilInputEventListener* _Listener <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; _Listener-&gt;SetIndex<span class="br0">&#40;</span> IndexPool.<span class="me1">Reserve</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">ListenerRemoved</span><span class="br0">&#40;</span> StencilInputEventListener* _Listener <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; IndexPool.<span class="me1">Release</span><span class="br0">&#40;</span> _Listener-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">DetectListeningIndex</span><span class="br0">&#40;</span> MouseEventMove &amp;E <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">int</span> Pixel = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; Renderer = &#8230; ;<br />
&nbsp; &nbsp; Pixel = Renderer-&gt;ReadStencilPoint<span class="br0">&#40;</span> E.<span class="me1">X</span>, E.<span class="me1">Y</span> <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; MouseMovedListeningIndex = Pixel;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">MouseMoved</span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span> MouseEventMove&nbsp; &nbsp; &nbsp; &nbsp; &amp;E <span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !LeftDown &amp;&amp; !RightDown &amp;&amp; !MiddleDown <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> iLastIndex = MouseMovedListeningIndex;<br />
&nbsp; &nbsp; &nbsp; &nbsp; DetectListeningIndex<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> iLastIndex != MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> MouseOverListener != <span class="kw2">NULL</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MouseOverListener-&gt;MouseOut<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MouseOverListener = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;MouseMoved<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> MouseOverListener == <span class="kw2">NULL</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MouseOverListener = pL;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MouseOverListener-&gt;MouseOver<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;<br />
<span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">MouseButtonUp</span>&nbsp; &nbsp; <span class="br0">&#40;</span> MouseEventButtonUp&nbsp; &nbsp; &amp;E <span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span> E.<span class="me1">Button</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_LEFT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; LeftDown = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_RIGHT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; RightDown = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_MIDDLE:<br />
&nbsp; &nbsp; &nbsp; &nbsp; MiddleDown = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;MouseButtonUp<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;<br />
<span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">MouseButtonDown</span>&nbsp; <span class="br0">&#40;</span> MouseEventButtonDown&nbsp; &amp;E <span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span> E.<span class="me1">Button</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_LEFT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; LeftDown = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_RIGHT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; RightDown = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="kw1">case</span> BUTTON_MIDDLE:<br />
&nbsp; &nbsp; &nbsp; &nbsp; MiddleDown = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;MouseButtonDown<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;<br />
<span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">MouseButtonClick</span> <span class="br0">&#40;</span> MouseEventButtonClick &amp;E <span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;MouseButtonClick<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">KeyDown</span><span class="br0">&#40;</span> KeyboardEventKeyDown &amp;E <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;KeyDown<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> StencilInputEventDispatcher::<span class="me2">KeyUp</span><span class="br0">&#40;</span> KeyboardEventKeyUp &amp;E <span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; EventListenerCollector&lt; StencilInputEventListener &gt;::<span class="me2">ListenerList</span>::<span class="me2">iterator</span> It = Listeners.<span class="me1">begin</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span> It != Listeners.<span class="me1">end</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StencilInputEventListener *pL = *It;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> pL-&gt;GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span> == MouseMovedListeningIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span> *It <span class="br0">&#41;</span>-&gt;KeyUp<span class="br0">&#40;</span> E <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ++It;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Mając tak napisany obiekt, wystarczy go podpiąć do instancji InputManager (a tą polecam przechowywać jako np. singleton).</p>
<p>Wspomnę jeszcze o tym, że jak chcemy zmieniać aktywny obiekt za pomocą klawiatury np. poprzez TAB/Shift+TAB to trzeba odrobinę zmodyfikować implementację StencilInputEventDispatcher, ale to już zostawiam wytrwałym którzy tu dobrneli i jeszcze mają ochotę na wykorzystanie fragmentów mojej implementacji :D.</p>
<p>Przejdźmy do sedna, czyli jak zaimplementować kontrolkę reagującą na zdarzenia? Nic prostrzego, jedyne wymagania od takiej klasy to dziedziczenie po StencilInputEventListener aby móc ją zarejestrować w dispatcherze oraz to żeby się go posłuchała i renderowała się do stencila z podanym przez niego indeksem</p>
<p>prawie pseudo kod:</p>
<div class="codesnip-container" >
<div class="codesnip">class Button3D : public StencilInputEventListener, public SceneNode<br />
<span class="br0">&#123;</span><br />
public:<br />
&nbsp; &nbsp; &#8230;<br />
&nbsp; &nbsp; <span class="kw4">int</span> GetIndex<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> Index;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> SetIndex<span class="br0">&#40;</span> <span class="kw4">int</span> iIndex <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Index = iIndex;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &#8230;<br />
&nbsp; &nbsp; <span class="me1">virtual</span> <span class="kw4">void</span> Render<span class="br0">&#40;</span> IRenderer *Renderer <span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Renderer-&gt;SetStencilOp<span class="br0">&#40;</span> IRenderer::<span class="me2">STENCIL_MODE_ALWAYSPASS</span>, Index <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Renderer-&gt;RenderMeshData<span class="br0">&#40;</span> MeshData <span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; Mesh *MeshData;<br />
<span class="br0">&#125;</span>;</div>
</div>
<p>IRenderer to jak sama nazwa wskazuje interfejs poprzez ktory dostajemy sie do renderera, tu zamiast niego wystarczy wykorzystać swój własny, lub bezpośrednio się odwołać do funkcji danego API. SceneNode to używana przeze mnie klasa pomocnicza implementująca większośc funkcji węzła w grafie sceny. Dla prostych obiektów wystarczy przeciążyć metodę Render. </p>
<p>Dalej to już zabawa z obsługą zdarzeń. Przycisk jak to przyciski powinny mieć w swoim zwyczaju powinien przeciążyć zdarzenie MouseButtonDown i odpowiednio na nie zareagować. Natomiast bardziej złożone kontrolki mogą zawierać kontrolki podrzędne implementujące interfejs słuchacza dispatchera. Pozostawiam to już Wam. </p>
<h3>Podsumowanie</h3>
<p>Opisałem przykład implementacji przekazywania zdarzeń do kontrolek 3D, który mi osobiście narazie wystarcza, jeżeli ktoś ma jakieś pytania i/lub pomysły na dalszy rozwój to czekam na komentarze.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=276&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BioShoot</title>
		<link>http://www.mi-ku.net/?p=272&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=272&amp;langswitch_lang=en#comments</comments>
		<pubDate>Mon, 02 Nov 2009 13:22:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[projects]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[popcap]]></category>
		<category><![CDATA[project]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=272</guid>
		<description><![CDATA[Wprowadziłem kilka poprawek:

Kolizje organizm-organizm,
kolizje organizm-pocisk.
śmierć gracza.
dwóch mobilnych &#8220;przeciwników&#8221;,
trochę ładniejsze mutowanie,
double-click lewym przyciskiem myszy ustawia cel do strzelania, czyli teraz można poruszać się i strzelać w różnych kierunkach
minimalna optymalizacja kodu

Przez te poprawki &#8220;gra&#8221; nabrała trochę sensu, natomiast brakuje jeszcze celu gry, a tym w zamierzeniu ma być na dojście do odpowiedniego miejsca lub wyeliminowanie wszystkich przeciwników.
Do [...]]]></description>
			<content:encoded><![CDATA[<p>Wprowadziłem kilka poprawek:</p>
<ul>
<li>Kolizje organizm-organizm,</li>
<li>kolizje organizm-pocisk.</li>
<li>śmierć gracza.</li>
<li>dwóch mobilnych &#8220;przeciwników&#8221;,</li>
<li>trochę ładniejsze mutowanie,</li>
<li>double-click lewym przyciskiem myszy ustawia cel do strzelania, czyli teraz można poruszać się i strzelać w różnych kierunkach</li>
<li>minimalna optymalizacja kodu</li>
</ul>
<p>Przez te poprawki &#8220;gra&#8221; nabrała trochę sensu, natomiast brakuje jeszcze celu gry, a tym w zamierzeniu ma być na dojście do odpowiedniego miejsca lub wyeliminowanie wszystkich przeciwników.</p>
<h3>Do pobrania</h3>
<p><a href="http://www.mi-ku.net/projekty/BioShoot/BioShootR2.zip" >http://www.mi-ku.net/projekty/BioShoot/BioShootR2.zip</a></p>
<h3>Screen shoot&#8217;y</h3>
<p><img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot06.gif" alt="BioShootR2 Screenshoot 1"></p>
<p><img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot07.gif" alt="BioShootR2 Screenshoot 2"></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=272&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rapid Game Prototyping</title>
		<link>http://www.mi-ku.net/?p=266&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=266&amp;langswitch_lang=en#comments</comments>
		<pubDate>Sat, 31 Oct 2009 23:00:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[Rapid Game Prototyping]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=266</guid>
		<description><![CDATA[W zasdzie nie chcę się powtarzać bo na ten temat wypowiedziały już się osoby bardziej zaznajomione z tematem więc dam linka który prowadzi do kolejnych ciekawych artykułów/informacji:
http://www.kloonigames.com/blog/general/articles-about-rapid-game-prototyping
Dla czego o tym temacie wspominam? Otóż na specjalizacji na studiach dostaliśmy zadanie własnie stworzenia prototypu gry w jak najkrótszym czasie. Czyli chcąc nie chcąc (bardziej chcąc :D ) [...]]]></description>
			<content:encoded><![CDATA[<p>W zasdzie nie chcę się powtarzać bo na ten temat wypowiedziały już się osoby bardziej zaznajomione z tematem więc dam linka który prowadzi do kolejnych ciekawych artykułów/informacji:</p>
<p><a href="http://www.kloonigames.com/blog/general/articles-about-rapid-game-prototyping">http://www.kloonigames.com/blog/general/articles-about-rapid-game-prototyping</a></p>
<p>Dla czego o tym temacie wspominam? Otóż na specjalizacji na studiach dostaliśmy zadanie własnie stworzenia prototypu gry w jak najkrótszym czasie. Czyli chcąc nie chcąc (bardziej chcąc :D ) musiałem coś zrobić. Oto wynik pracy która zajęła około 40 godzin:</p>
<h3>Opis gry</h3>
<p>Jako, że nie mielismy wyznaczonego jasno tematu prototypu to w grze jesteśmy sobie dziwnym organizmem w dziwnym świecie. Chodzi o to żeby zbierać mutatory (power upy) i nie dać się zabić w świecie w którym się znaleźlismy. </p>
<p>Dostępne mutatory:<br />
Zielony &#8211; Ciało<br />
Czerwony &#8211; Działko (oryginalna nazwa?  )<br />
Biały &#8211; Osłona<br />
Niebieski &#8211; Głowa przy pomocy której możemy się poruszać</p>
<h3>Sterowanie</h3>
<p>LPM &#8211; Poruszanie<br />
PPM &#8211; Strzelanie (jeżeli łyknęlismy mutator do strzelania)</p>
<p>Edytor<br />
TAB x1 &#8211; tryb edycji świata<br />
TAB x2 &#8211; tryb edycji mutatorów</p>
<p>W trybie edytora polecam pobawić się: LPM, PPM, Środkowy przycisk myszy, Del, Shift, Ctrl. Edytor jest w miarę intuicyjny więc się nie rozpisuje &#8211; polecam się pobawić. Przeciwnicy są zhardkodowani.</p>
<h3>Co nie zostało zrobione</h3>
<p>- Tarcie w kolizjach &#8211; teraz można się nieźle zaplątać:)<br />
- kolizje między organizmami<br />
- kolizje organizm -> &#8220;pocisk&#8221; <- co oczywiście chwilowo psuje cały efekt i nie pokazuje gameplayu - co w zasadzie miało być kwintesencją prototypu hehe, ale dodam w kolejnej wersji.<br />
- te kolizje co są nie są oparte na żadnym drzewie ósemkowym itp. w związku z tym gra potrafi nieźle przyciąć kompa </p>
<h3>Do pobrania</h3>
<p><a href="http://www.mi-ku.net/projekty/BioShoot/BioShootR1.zip">http://www.mi-ku.net/projekty/BioShoot/BioShootR1.zip</a></p>
<h3>Screen shooty</h3>
<p><img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot05.jpg" alt="BioShoot title screen" /></p>
<p><img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot01.gif" alt="BioShoot screen shoot 1" /></p>
<p>Po zjedzeniu zielonego mutatora:<br />
<img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot02.gif" alt="BioShoot screen shoot 1" /></p>
<p>Pod ostrzałem :)<br />
<img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot03.gif" alt="BioShoot screen shoot 1" /></p>
<p>Z edytora świata:<br />
<img src="http://www.mi-ku.net/projekty/BioShoot/bioshoot04.gif" alt="BioShoot screen shoot 1" /></p>
<h3>Technikalia</h3>
<p>projekt został całkowicie napisany pod frameworkiem PopCap. Z frameworka wykorzystałem głównie: rysowanie przez Graphics, Image, XML, Dźwięki, Obsługę wejścia. Poza frameworkiem dopisalem kilka funkcji pomocniczych do Graphics&#8217;a i prostą fizykę sprężyn.</p>
<p>Technicznie trochę prze-engineerowałem jak to się mawia, mam pełny polimorfizm, możliwość dodawania nowych nodów, powerupów, kontrollerów dla organizmów(np. kolejne AI), możliwe jest też napisanie całkowicie innych broni i podpięcie ich w łatwy sposób, np zdalnie naprowadzanych pocisków itp. Wrogowie mogą być również mobilni. Dużo czasu też poświęciłem edytorowi który przynajmniej umożliwia edycje świata i powerupów bo w xmlu bym się zachetał to pisać.</p>
<p>Dźwięki zapożyczyłem ze Starcrafta, więc nie mam do nich praw&#8230;.. aha odpalając gre lepiej mieć przyciszony dźwięk :P</p>
<h3>Podsumowanie</h3>
<p>W sumie całość nie jest jeszcze skończona, ale nie mogłem się powstrzymać przed umieszczeniem aktualnej wersji :) a obawiam się że teraz mogę nie mieć już czasu na tą gierkę. Gdy zaimplementuje kolizje pocisków z organizmami i co za tym idzie śmierć gracza to dopiero wtedy okaże się czy gameplay ma sens.</p>
<p>Miłej zabawy z niedokończonym prototypem :) :) :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=266&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programowanie gier &amp; Biofeedback</title>
		<link>http://www.mi-ku.net/?p=258&amp;langswitch_lang=en</link>
		<comments>http://www.mi-ku.net/?p=258&amp;langswitch_lang=en#comments</comments>
		<pubDate>Sun, 11 Oct 2009 21:51:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[projects]]></category>
		<category><![CDATA[Biofeedback]]></category>
		<category><![CDATA[game programming]]></category>

		<guid isPermaLink="false">http://www.mi-ku.net/?p=258</guid>
		<description><![CDATA[Pod koniec zeszłego semestru musiałem wybrać specjalizację kierunku który studiuję (Informatyka na PJWSTK). Do wyboru miałem 

Bazy danych
Programowanie aplikacji biznesowych
Sieci komputerowe
Multimedia
Robotyka
Multimedia &#8211; programowanie gier

W zasadzie tematyka każdej specjalizacji jakoś bardziej lub mniej mnie interesuje i miałem spory dylemat którą wybrać, w rachubę wchodziło też wybranie dwóch specjalizacji i realizowanie pracy inżynierskiej pod kątem obu. Po [...]]]></description>
			<content:encoded><![CDATA[<p>Pod koniec zeszłego semestru musiałem wybrać specjalizację kierunku który studiuję (Informatyka na PJWSTK). Do wyboru miałem </p>
<ul>
<li>Bazy danych</li>
<li>Programowanie aplikacji biznesowych</li>
<li>Sieci komputerowe</li>
<li>Multimedia</li>
<li>Robotyka</li>
<li>Multimedia &#8211; programowanie gier</li>
</ul>
<p>W zasadzie tematyka każdej specjalizacji jakoś bardziej lub mniej mnie interesuje i miałem spory dylemat którą wybrać, w rachubę wchodziło też wybranie dwóch specjalizacji i realizowanie pracy inżynierskiej pod kątem obu. Po długim namyśle wybrałem jakże egzotyczną jak na polskie realia (chociaż ostatnio sytuacja się poprawia) specjalizację &#8220;programowanie gier&#8221;, gdyż ta bezpośrednio umożliwia mi realizację jednego z pomysłów które siedzą mi w głowie od dawna.</p>
<h3>Pomysł</h3>
<p>Chcę wykonać grę która będzie wykorzystywała specjalny &#8220;kontroler&#8221; służący do pomiaru aktywności umysłu, której celem będzie osiąganie stanu relaksu przez grającego. Pomysłów na realizację mam kilka, jeden (podrzucony przez jednego z prowadzących) uwzględnia dwóch graczy gdzie wygrywa ten który szybciej się zrelaksuje, inne pomysły to mini gry w których grający będzie musiał osiągnąć oczekiwany efekt audio-wizualny poprzez relaksację. Taka technika nosi nazwę Biofeedback&#8217;u, czyli sprzężenia zwrotnego utworzonego na podstawie odczytu i interpretowania jakiegoś sygnału generowanego przez człowieka i podawania informacji zwrotnych do jakiegoś zmysłu/zmysłów ludzkiego z komputera. Do pomiaru aktywności umysłu chcę wykorzystać metodę pomiaru rezystancji naskórka (galvanic skin response) która jest związana z opornością układu nerwowego, który z kolei pośrednio odpowiada aktywności umysłu.</p>
<p>Biofeedback służący do relaksacji ma poważne zastosowanie w np. w psychoterapii przy leczeniu między innymi ADHD. Może być też wykorzystywany przez ludzi żyjących w ciągłym stresie. W zasadzie zastosowań jest wiele, także mogę coś zrobić co się być może przyda innym. </p>
<h3>Wstępna realizacja części sprzętowej</h3>
<p>Jako, że do metody którą wybrałem potrzebne jest mi urządzenie komunikujące się z komputerem, a na czas testów nie chciałem projektować własnego układu opartego o mikrokontroler. Między innymi w związku z małym doświadczeniem na tym polu. To wpadłem na pomysł przerobienia analogowego joypada na moje potrzeby. Sposób był prosty, gałki analogowe działają na podstawie odczytanej rezystancji z potencjometru połączonego z gałką sterującą. To jak już pewnie wiecie zamiast potencjometru mechanicznego wystarczy podłączyć rezystancję &#8220;ludzką&#8221;, oczywiście wbudowane potencjometry mają o wiele mniejszą rezystancję niż skóra i wymagało to drobnych przeróbek, jednak wstępnie się udało. Elektrody na palce wykonałem z rzepów do których wszyłem splotkę przewodzącą prąd (to było najlepsze co mogłem zmontować z materiałów znalezionych w domu), które sprawdzają się całkiem nieźle. W ten oto sposób otrzymałem proste, działające jako tako urządzenie, które po wstępnych testach zachowuje się zgodnie z moimi przewidywaniami, czyli jest
<ul>
<li>nie dokładne &#8211; w związku małą rozdzielczość pomiaru, joypad przewidywał tylko 256 próbek, które do gier oczywiście w zupełności wystarczają, jednak tutaj przydało by się przynajmniej tą dwójkę podnieść dwie potęgi wyżej :)</li>
<li>nie stabilny odczyt &#8211; potrzeba kilka minut na stabilizację układu. To raczej w związku z moją przeróbką</li>
<li>Wymagana kalibracja dodatkowym potencjometrem wykonana pod użytkownika</li>
</ul>
<p>W każdym bądź razie się nie zrażam bo jak na jeden dzień pracy wyniki są zadowalające. W oknie kalibracji joypada da się zaobserwować zmiany rezystancji układu nerwowego. Nawet nie wiedzialem jak bardzo potrafi organizm zareagować na pewne bodźce, np. plasknięcie się po twarzy powoduje gwałtowne przesunięcie wskaźnika kontrolera :) a słuchanie relaksującej muzyki powoduje powolny powrót wskaźnika na dawne miejsce. Kontynuacja relaksacji powoduje jeszcze większe przesunięcie wskaźnika co oznacza, że osiągnąłem większy spokój niż przed zastosowaniem wspomnianego bodźca. Wracając do samego urządzenia to finalnie postaram się zrobić własne na USB typu HID wykorzystujące jakiś mikrokontroler.</p>
<p>Wynik przeróbki joypada:<br />
<img src="http://www.mi-ku.net/projekty/biofeedback/images/device01.jpg" alt="usb joypad modified to be a biofeedback device"></p>
<h3>Co dalej?</h3>
<p>Pozostaje mi między innymi wymyśleć co dokładnie będzie tematem pracy inżynierskiej i zacząć powoli ją robić (o ile zostanie zaakceptowany :P ). </p>
<p>Sam pomysł biofeedbacku można rozwinąć i połączyć z wspomaganiem samej relaksacji poprzez w pewnym sensie wymuszanie odpowiedniej aktywności umysłowej poprzez pewne bodźce fizyczne, np. poprzez tzw. szumy dudnieniowe służące do synchronizacji półkul mózgowych do pracy w odpowiedniej częstotliwości.</p>
<p>Zainteresowanych odsyłam do poszukania w internecie informacji pod hasłami: biofeedback, gsr, hemi-sync. Swego czasu powstał komercyjny produkt, który w zasadzie odpowiada prawie 1 do 1 temu co chcę zrobić, można o nim poczytać na: <a href="http://www.relaksacja.pl">www.relaksacja.pl</a>. Do hemi-sync polecam programik Gnuaural. To chwilowo na tyle.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mi-ku.net/?feed=rss2&amp;p=258&amp;langswitch_lang=en</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
