<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8323132172904612534</atom:id><lastBuildDate>Fri, 13 Feb 2026 23:24:28 +0000</lastBuildDate><category>c++</category><category>Visual Studio</category><category>assembler</category><category>krótka recenzja</category><category>Ogólne</category><title>mateusz.semegen::devblog</title><description>&quot;chciałbym poczytać o tym, jak pierwszy raz uciekłeś z domu&quot;</description><link>http://msemegen.blogspot.com/</link><managingEditor>noreply@blogger.com (msemegen)</managingEditor><generator>Blogger</generator><openSearch:totalResults>41</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-6467508802518048918</guid><pubDate>Mon, 15 Jul 2013 08:42:00 +0000</pubDate><atom:updated>2013-07-15T10:42:48.516+02:00</atom:updated><title>OpenGL + Shadery</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
W tej części kursu dotyczącego malowania w OpenGL , dodamy nieco życia do naszej nudnej sceny a także zapoznamy się z programowalnym potokiem renderowania. Zatem do dzieła.&amp;nbsp;&lt;/div&gt;
&lt;h4 style=&quot;text-align: justify;&quot;&gt;
Shadery!&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Shader to niewielki program uruchamiany na karcie graficznej. W naszym przypadku (staramy się trzymać kompatybilność z OpenGL ES 2.0) rozróżniamy dwa rodzaje shaderów: Vertex i Fragment.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Vertex shader&lt;/b&gt; jest wykonywany dla każdego wierzchołka przekazywanej geometrii. Odpowiada on za liczenie pozycji wierzchołka, najczęściej na podstawie macierzy (projekcji, modelu lub widoku) oraz jego początkowej pozycji. Może on wykonać także dodatkowe operacje, których wyniki mogą być używane w późniejszych fazach potoku renderowania. Zadaniem &lt;b&gt;fragment shadera&lt;/b&gt; zaś, jest obliczenie końcowego koloru piksela. To w nim implementowane jest teksturowanie lub oświetlenie&lt;i&gt; per-pixel&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Do pisania shaderów będziemy używać języka GLSL. Jest on bardzo podobny do C, pomijając kilka różnic. Przede wszystkim mamy do dyspozycji nowe typy: wektory i macierze wraz z pełną paletą wbudowanych funkcji. Dodatkowo, dodanych zostało kilka modyfikatorów, które zostaną omówione w dalszej części kursu.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Z poziomu GLSL nie mamy dostępu do wskaźników. Pętle muszą być rozwijalne na etapie kompilacji a długość programu jest ograniczona dostępnymi zasobami sprzętowymi. Widać zatem, że mamy do czynienia z językiem bardziej restrykcyjnym i przeznaczonym dla wyspecjalizowanych celów.&lt;/div&gt;
&lt;h4&gt;
Modyfikatory&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Nowe ty&lt;span style=&quot;font-family: inherit;&quot;&gt;py modyfikatorów t&lt;/span&gt;o uniform, attribute oraz varying. &lt;b&gt;Uniform &lt;/b&gt;jest to globalna (dla pojedynczego shadera) stała, której wartość została przekazana z zewnątrz. Dzięki tego typu konstrukcji, możemy przekazywać do shadera wcześniej wyliczone wartości dotyczące położenia kamery czy transformacji widoku. &lt;b&gt;Atrybut &lt;/b&gt;(&lt;i&gt;attribute&lt;/i&gt;) bezpośrednio odnosi się do wierzchołka. Jest to przekazywana dla każdego wierzchołka właściwość, np. położenie, kolor, normalna czy pozycja tekstury. Na samym końcu mamy &lt;b&gt;varying&lt;/b&gt;. Tym modyfikatorem oznaczamy zmienne, które chcemy przekazać z Vertex shadera do Fragment shadera.&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Hello world&amp;nbsp;&lt;/h4&gt;
&lt;div&gt;
Czas więc osobiście zapoznać się z naszymi shaderami. Na pierwszy ogień pójdzie &lt;b&gt;Vertex shader&lt;/b&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;attribute&amp;nbsp;vec4&amp;nbsp;attrPosition;
attribute&amp;nbsp;vec4&amp;nbsp;attrColor;
 
uniform&amp;nbsp;mat4&amp;nbsp;unfModel;
uniform&amp;nbsp;mat4&amp;nbsp;unfProjection;
 
varying&amp;nbsp;vec3&amp;nbsp;vygColor;
 
void&amp;nbsp;main()&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;{
 gl_Position&amp;nbsp;=&amp;nbsp;unfProjection&amp;nbsp;*&amp;nbsp;unfModel&amp;nbsp;*&amp;nbsp;attrPosition;
 vygColor&amp;nbsp;=&amp;nbsp;attrColor.rgb;
}&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jak więc widać, jest to niewielki program, wykonujący podstawowe opracje. Pierwsza rzaczą, która z pewnością rzuca się w oczy to obecność funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px; text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;&amp;nbsp;&lt;/span&gt;Jej przeznaczenie jest oczywiste - punkt wejściowy shadera. Kolejnym interesującym zjawiskiem jest&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;gl_Position&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px; text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;&amp;nbsp;&lt;/span&gt;Jak widać, jest to zmienna. Nie jest jednak nigdzie zadeklarowana a mimo wszystko jest używana. GLSL posiada zestaw wbudowanych zmiennych, do których można zapisywać dane będące użyte w kolejnych etapach renderowania. Jedną z nich jest właśnie gl_Position. Mamy do niej dostęp tylko z poziomu Vertex shadera. &amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Uniformami są tutaj macierze 4x4 (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;mat4&lt;/span&gt;)&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;unfModel&lt;/span&gt;&amp;nbsp;raz&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;unfProjection&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;&amp;nbsp;&lt;/span&gt;Wartości ich zostały wyliczone w programie głównym, zaś tu zostały tylko przekazane i wykorzystane do wyliczenia końcowej pozycji wierzchołka. Warto tutaj zaznaczyć, że nie możemy tworzyć uniformów zaczynających się prefiksem gl_.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jako, że na nasz wierzchołek składa się tylko pozycja i kolor, takie też atrybuty przekazujemy do shadera (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;attrPosition&amp;nbsp;&lt;/span&gt;oraz&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;attrColor&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;. Tutaj jednak pojawia się problem. Dostęp do atrybutów mamy tylko z poziomu &amp;nbsp;vertex shadera, zaś w nim nie możemy pomalować piksela, przekazanym w atrybucie kolorem. Musimy zatem przekazać kolor do fragment shadera, w którym to zostanie on odpowiednio wykorzystany. Z pomocą przychodzi tu zmienna&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;vygColor&lt;/span&gt;, która została oznaczona wcześniej wspomnianym modyfikatorem&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;varying&lt;/span&gt;.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Na sam koniec zostało wyliczenie końcowej pozycji wierzchołka na ekranie. Jak widać jest to iloczyn macierzy projekcji, modelu (macierz będąca wynikiem wszystkich podstawowych transformacji na obiekcie) oraz początkowego położenia wierzchołka. Jak pamiętamy z podstawówki, lub co ambitniejszych przedszkoli, mnożenie macierzy nie jest przemienne, więc musimy zachować prezentowaną tu kolejność.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;Fragment shader&lt;/b&gt; jest znacznie krótszy:&lt;/div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;varying&amp;nbsp;vec3&amp;nbsp;vygColor;
 
void&amp;nbsp;main()
{
 gl_FragColor&amp;nbsp;=&amp;nbsp;vec4(vygColor.r,&amp;nbsp;vygColor.g,&amp;nbsp;vygColor.b,&amp;nbsp;1.0);
}&lt;/pre&gt;
&lt;/div&gt;
Mamy tu tylko przekazany z poprzedniego shadera kolor wierzchołka oraz przypisanie go do wyjściowej zmiennej&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;gl_FragColor&lt;/span&gt;.&lt;br /&gt;
&lt;h4&gt;
Tymczasem w C++...&lt;/h4&gt;
&lt;div&gt;
Mając gotowe shadery, możemy zająć się ich kompilacją. Ciekawostką jest to, że będziemy to robić z poziomu naszego programu głównego, w trakcie inizjalizacji. Wykorzystamy do tego niewielką funkcję:&amp;nbsp;&lt;/div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;compileShader(GLuint&amp;nbsp;*pOutShader,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;char&lt;/span&gt;&amp;nbsp;*szSource,&amp;nbsp;ShaderType&amp;nbsp;type)
{
 *pOutShader&amp;nbsp;=&amp;nbsp;glCreateShader(type);
 
 glShaderSource(*pOutShader,&amp;nbsp;1,&amp;nbsp;&amp;amp;szSource,&amp;nbsp;NULL);
 glCompileShader(*pOutShader);
 
 GLint&amp;nbsp;iCompileStatus&amp;nbsp;=&amp;nbsp;GL_FALSE;
 glGetShaderiv(*pOutShader,&amp;nbsp;GL_COMPILE_STATUS,&amp;nbsp;&amp;amp;iCompileStatus);
 &lt;span style=&quot;color: blue;&quot;&gt;return&lt;/span&gt;&amp;nbsp;iCompileStatus&amp;nbsp;==&amp;nbsp;GL_TRUE;&amp;nbsp;&lt;/pre&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Skupimy się tu przede wszystkim na API OpenGL. Na początek tworzymy obiekt shadera, za pomocą funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glCreateShader&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Przyjmuje ona typ shadera:&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_VERTEX_SHADER&amp;nbsp;&lt;/span&gt;lub&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_FRAGMENT_SHADER&lt;/span&gt;. Następnie kojarzymy dany obiekt z konkretnym kodem źródłowym za pomocą&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glShaderSource&lt;/span&gt;. Funkcja ta przyjmuje tablicę cstringów, której rozmiar określa drugi parametr (w naszym przypadku&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;1&lt;/span&gt;) . Jeśli każdy przekazany tekst kończy się zerem (czyli jest standardowym cstringiem), możemy ustawić ostatni parametr na&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;NULL&lt;/span&gt;.W przeciwnym razie, musimy przekazać długość każdego z podczepianych źródeł. Jesteśmy zatem gotowi do kompilacji, która następuje po wywołaniu&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glCompileShader&lt;/span&gt;. Status kompilacji możemy pobrać korzystając z funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glGetShaderiv&amp;nbsp;&lt;/span&gt;do której przekazać trzeba obiekt właśnie kompilowanego shadera (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;*pOutShader&lt;/span&gt;), oraz wskaźnik na zmienną która przechowa sam status (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;iCompileStatus&amp;nbsp;&lt;/span&gt;-&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_TRUE&amp;nbsp;&lt;/span&gt;dla sukcesu oraz&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_FALSE&amp;nbsp;&lt;/span&gt;dla porażki).&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Mając skompilowane shadery, możemy je zlinkować w jeden program:&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;linkProgram(GLuint&amp;nbsp;*pOutProgram,&amp;nbsp;GLuint&amp;nbsp;uVertexShader,&amp;nbsp;GLuint&amp;nbsp;uFragmentShader)
{
 *pOutProgram&amp;nbsp;=&amp;nbsp;glCreateProgram();
 glAttachShader(*pOutProgram,&amp;nbsp;uVertexShader);
 glAttachShader(*pOutProgram,&amp;nbsp;uFragmentShader);
 
 glLinkProgram(*pOutProgram);
 
 GLint&amp;nbsp;iLinkStatus&amp;nbsp;=&amp;nbsp;GL_FALSE;
 glGetProgramiv(*pOutProgram,&amp;nbsp;GL_LINK_STATUS,&amp;nbsp;&amp;amp;iLinkStatus);
 
 &lt;span style=&quot;color: blue;&quot;&gt;return&lt;/span&gt;&amp;nbsp;iLinkStatus&amp;nbsp;==&amp;nbsp;GL_TRUE;
}&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Po stworzeniu obiektu programu za pomocą&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glCreateProgram&lt;/span&gt;&amp;nbsp;dołączamy za pomocą&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glAttachShader&amp;nbsp;&lt;/span&gt;wcześniej skompilowane shadery. Teraz zostaje nam już tylko zlinkować program (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glLinkProgram&lt;/span&gt;) oraz sprawdzić za pomocą&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glGetProgramiv&amp;nbsp;&lt;/span&gt;wynik owej operacji.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jesteśmy już o krok od namalowania naszego upragnionego kwadracika. Zostało nam jeszcze tylko pobranie informacji o położeniu atrybutów oraz uniformów. Zrobi to dla nas poniższy kod:&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;glBindAttribLocation(uProgram,&amp;nbsp;0,&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;attrPosition&quot;&lt;/span&gt;);
glBindAttribLocation(uProgram,&amp;nbsp;1,&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;attrColor&quot;&lt;/span&gt;);
 
iProjectionUniform&amp;nbsp;=&amp;nbsp;glGetUniformLocation(uProgram,&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;unfProjection&quot;&lt;/span&gt;);
iModelUniform&amp;nbsp;=&amp;nbsp;glGetUniformLocation(uProgram,&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;unfModel&quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Warto zwrócić uwagę, że atrybutowi przypisujemy ID po jego nazwie w shaderze (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glBindAttribLocation&lt;/span&gt;), zaś ID uniformu jest pobierane (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glGetUniformLocation&lt;/span&gt;), także na podstawie nazwy, którą nadaliśmy mu w kodzie shadera. Tym akcentem kończymy incjalizację aplikacji. Możemy zająć się pętlą główną.&lt;br /&gt;
&lt;h4&gt;
Malowanie&lt;/h4&gt;
W pętli głównej możemy zobaczyć taki oto kawałek kodu:&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;glUseProgram(uProgram);
glUniformMatrix4fv(iProjectionUniform,&amp;nbsp;1,&amp;nbsp;GL_FALSE,&amp;nbsp;(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;*)&amp;amp;(projection[0]));
glUniformMatrix4fv(iModelUniform,&amp;nbsp;1,&amp;nbsp;GL_FALSE,&amp;nbsp;(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;*)&amp;amp;(model[0]));
 
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
 
glVertexAttribPointer(0,&amp;nbsp;4,&amp;nbsp;GL_FLOAT,&amp;nbsp;GL_FALSE,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex),&amp;nbsp;vertices);
glVertexAttribPointer(1,&amp;nbsp;3,&amp;nbsp;GL_FLOAT,&amp;nbsp;GL_FALSE,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex),&amp;nbsp;(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;*)(vertices)&amp;nbsp;+&amp;nbsp;4);
 
glDrawElements(GL_TRIANGLES,&amp;nbsp;6,&amp;nbsp;GL_UNSIGNED_SHORT,&amp;nbsp;faces);
 
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
 
glUseProgram(0);&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Pierwszą funkcją, na którą powinniśmy zwrócić uwagę to&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glUseProgram&lt;/span&gt;. Jako parametr podajemy jej obiekt wcześniej zlinkowanego programu. Od tej chwili wszystkie operacje, dotyczące shadera, będą dokonywały się właśnie na owym programie.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Mając ustawiony program, możemy przekazać shaderowi macierze projekcji oraz modelu. Robimy to za pomocą funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glUniformMatrix4fv&lt;/span&gt;. Warto zaznaczyć, że jest to tylko jeden z wielu członków rodziny funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glUniform*&lt;/span&gt;. W zależności od typu przyjmowanych parametrów, przesyłają one do shadera różne typy danych. W naszym przypadku, dla uniformu o ID&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;iProjectionUniform&lt;/span&gt;, przekazujemy jedną (parametr drugi określa ilość), nietransponowaną (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_FALSE&lt;/span&gt;) macierz 4x4 -&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;projection&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&amp;nbsp; Analogicznie wygląda to dla macierzy modelu.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Następnie informujemy OpenGL z jakich atrybutów wierzchołka będziemy korzystać (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glEnableVertexAttribArray&lt;/span&gt;). Będzie to oczywiście pozycja (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;0&lt;/span&gt;) oraz kolor (&lt;span style=&quot;font-family: Consolas; font-size: x-small;&quot;&gt;1&lt;/span&gt;), których odpowiednie ID zostały przypisane za pomocą&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glBindAttribLocation&lt;/span&gt;.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Przyjrzyjmy się jeszcze, jak wygląda nasz wierzchołek:&lt;/div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;struct&lt;/span&gt;&amp;nbsp;ColorRGB
{
 &lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;&amp;nbsp;r,&amp;nbsp;g,&amp;nbsp;b;
};
 
&lt;span style=&quot;color: blue;&quot;&gt;struct&lt;/span&gt;&amp;nbsp;Vertex
{
 vec4&amp;nbsp;position;
 ColorRGB&amp;nbsp;color;
};&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jak widać składa się on z pozycji, która jest czteroelementowym wektorem oraz koloru, który jest wyrażonymi składowymi R, G i B. Podstawowy typ danych to float. Informacje te, są niezbędne w następnym kroku:&lt;/div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;glVertexAttribPointer(0,&amp;nbsp;4,&amp;nbsp;GL_FLOAT,&amp;nbsp;GL_FALSE,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex),&amp;nbsp;vertices);
glVertexAttribPointer(1,&amp;nbsp;3,&amp;nbsp;GL_FLOAT,&amp;nbsp;GL_FALSE,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex),&amp;nbsp;(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;*)(vertices)&amp;nbsp;+&amp;nbsp;4);
&lt;/pre&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0VDDUsKpofga3UPASGJIOVTGBWedsZ8dl1LhPFuOJZfRn0bj6BTwn9l1MPcTPFHcesNCfq1fVnFlxPrdd2kRa7WLaaGpmsa1_qutB9E4YVZ0zIXQZwrvlmfNnNRl4ejSDFdUB2x0SmLg/s1600/draw1.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0VDDUsKpofga3UPASGJIOVTGBWedsZ8dl1LhPFuOJZfRn0bj6BTwn9l1MPcTPFHcesNCfq1fVnFlxPrdd2kRa7WLaaGpmsa1_qutB9E4YVZ0zIXQZwrvlmfNnNRl4ejSDFdUB2x0SmLg/s400/draw1.png&quot; width=&quot;306&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Przekazujemy tutaj informacje o dokładnym położeniu każdego atrybutu w naszej strukturze wierzchołka. Idąc od lewej pierwszy parametr to ID atrybutu. Drugi określa liczbę komponentów, z jakich składa się atrybut. Pozycja jest przedstawiana za pomocą współrzędnych X, Y, Z oraz W (4), zaś kolor ma składowe R, G, B (3). Kolejny parametr to typ danych - w naszym przypadku to float. Przekazywane dane nie są znormalizowane, więc czwarty parametr ustawiany jest na wartość&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;GL_FALSE&lt;/span&gt;. Jako, że wierzchołki wraz z atrybutami będą składowane w tablicy, musimy określić odległość (w bajtach) od odpowiadających sobie atrybutów - będzie to po prostu rozmiar struktury wierzchołka. Ostatni parametr to wskaźnik na pierwszy atrybut. W przypadku pozycji, będzie to po prostu adres pierwszego elementu tablicy, zaś pozycja koloru jest przesunięta o cztery zmienne typu float, ponieważ znajduje się za pozycją. Myślę, że na poniższym rysunku obok jest to przedstawione w bardziej czytelny sposób. Zostało zatem zawołanie funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glDrawElements&lt;/span&gt;, ale nie różni się ona niczym w porównaniu do poprzedniej części kursu.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Został nam do omówienia jeszcze jeden aspekt - samo budowanie macierzy widoku i modelu. Wykorzystałem do tego bibliotekę &lt;a href=&quot;http://sourceforge.net/projects/ogl-math/&quot; target=&quot;_blank&quot;&gt;GLM&lt;/a&gt;. Jest ona bardzo prosta i przyjemna w użyciu, także myślę, że nie istnieje tutaj potrzeba dokładnego omawiania kilku operacji które zostały wykonane za jej pomocą.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Źródła można pobrać &lt;a href=&quot;https://dl.dropboxusercontent.com/u/21426852/Blog/3%20-%20OpenGL.zip&quot; target=&quot;_blank&quot;&gt;tu&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/07/opengl-shadery.html</link><author>noreply@blogger.com (msemegen)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0VDDUsKpofga3UPASGJIOVTGBWedsZ8dl1LhPFuOJZfRn0bj6BTwn9l1MPcTPFHcesNCfq1fVnFlxPrdd2kRa7WLaaGpmsa1_qutB9E4YVZ0zIXQZwrvlmfNnNRl4ejSDFdUB2x0SmLg/s72-c/draw1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3243794149534043833</guid><pubDate>Fri, 12 Jul 2013 14:42:00 +0000</pubDate><atom:updated>2013-07-12T16:42:42.894+02:00</atom:updated><title>Macalna sciana</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
Dziś czas na kolejną, małą prezentację. Jak zwykle będzie ona związana z technologiami około Kinectowymi, które wypełniają aktualnie cały mój czas. Tym razem jednak, nie będzie ona dotyczyła typowego rozwiązania, opartego na gestach i machaniu rękami. Będzie to coś bardziej tradycyjnego - powierzchnia dotykowa, a dokładniej rzecz ujmując: zwykła ściana.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jak zatem zmienić ścianę w obiekt reagujący na macanie? Wystarczy w zasadzie sensor głębi (zalecany jest tu jednak Asus Xtion Pro) oraz odrobinę softu. Samo stworzenie tej wersji oprogramowania zajęło miesiąc i jest to jego dość wczesna wersja, co doskonale widać na poniższym filmie. Po zapewnieniu odpowiednich warunków, możemy delektować się jednak nieograniczoną radością z zabijania świń wypuszczanymi z procy ptakami, na każdej ścianie przed którą możemy postawić Kinecta.&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/Y47Nwvu24lM?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/07/macalna-sciana.html</link><author>noreply@blogger.com (msemegen)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-5376814756498589542</guid><pubDate>Wed, 22 May 2013 20:32:00 +0000</pubDate><atom:updated>2013-05-22T22:32:35.493+02:00</atom:updated><title>Nowy Kinect</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWre8TCX_OwCqr0I_nex6n1pg1sMXxSr7YgZ4xoTyEPGMxglQuUg8KNYSV4WjypaZonSdYH4d_G_YWgEpPuTsqXWawKZO6GbDjC9wdWmQlAKJzZuL6nbvrp1onuIepNbYriL8GAEZFQJU/s1600/xbox-one-kinect-sensor_1280.0_cinema_640.0.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;225&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWre8TCX_OwCqr0I_nex6n1pg1sMXxSr7YgZ4xoTyEPGMxglQuUg8KNYSV4WjypaZonSdYH4d_G_YWgEpPuTsqXWawKZO6GbDjC9wdWmQlAKJzZuL6nbvrp1onuIepNbYriL8GAEZFQJU/s400/xbox-one-kinect-sensor_1280.0_cinema_640.0.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;Jest! W końcu! Po trzech latach od prezentacji pierwszej generacji czujnika głębi sygnowanego logiem Microsoftu, wczoraj mieliśmy okazję zobaczyć jego następcę. Podczas trwania konferencji nie usłyszeliśmy o nim zbyt wiele, pomijając niewielki fragment podczas którego podziwialiśmy czułość na gesty oraz możliwości rozpoznawania mowy. O ile ta ostatnia funkcjonalność nie robi już dziś dużego wrażenia (mamy przecież Google Now czy Siri od Apple) to rozpoznawanie ruchów ręki czy dłoni, ciągle wydaje się możliwością zakrawającą of Science Fiction.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Dziś w sieci ukazał się krótki &lt;a href=&quot;http://gizmodo.com/the-xbox-ones-secret-killer-feature-getting-you-in-sh-509243228?utm_campaign=socialflow_gizmodo_facebook&amp;amp;utm_source=gizmodo_facebook&amp;amp;utm_medium=socialflow&quot; target=&quot;_blank&quot;&gt;film&lt;/a&gt;, na którym mogliśmy trochę bliżej poznać nowy kontroler do nadchodzącej konsoli Xbox. Zostało ujawnionych znacznie więcej szczegółów dotyczących działania urządzenia. Przede wszystkim została zmieniona technologia &quot;widzenia&quot; głębi. W aktualnej generacji wykorzystywany jest promiennik podczerwieni rzucający siatkę punktów, która po odpowiedniej analizie daje nam stosunkowo dokładne informacje o położeniu w przestrzeni trójwymiarowej. Jak już wspominałem we&amp;nbsp;&lt;a href=&quot;http://msemegen.blogspot.com/2013/01/kinect-wprowadzenie.html&quot; target=&quot;_blank&quot;&gt;wcześniejszej &lt;span id=&quot;goog_187136377&quot;&gt;&lt;/span&gt;notce&lt;/a&gt; zostało to opracowane przez PrimeSense. Tym razem Microsoft postanowił uniezależnić się od zewnętrznych instytucji i... przejął dwie mniejsze firmy zajmujące się tworzeniem sensorów 3D. W tym wypadku postawiono na technologię o nazwie &lt;a href=&quot;http://en.wikipedia.org/wiki/Time-of-flight_camera&quot; target=&quot;_blank&quot;&gt;Time of Light&lt;/a&gt;. W wielkim skrócie i uproszczeniu, mamy tutaj do czynienia z kamerą która potrafi mierzyć prędkość odbitego światła od poszczególnych obiektów sceny. Brzmi niesamowicie, ale jest to stosunkowo stara metoda wykorzystywana w dalmierzach laserowych. Tutaj jednak równocześnie dokonujemy pomiaru dla całej macierzy punktów. Warto zaznaczyć, że pierwsze tego typu kamery pojawiły na rynku się już w 2006 roku. Gdzie jest zatem postęp, którym tak bardzo chwali się Microsoft? Rozdzielczość. Nie ujawniono jeszcze dokładnej ilości odczytywanych pikseli, jednak już na pierwszej prezentacji można zauważyć, że poczyniono w tym zakresie znaczny progres. Przedstawiciel korporacji mówił o rozdzielczości HD, jednak myślę, że podobnie jak w pierwszej wersji sensora, siatka punktów została reskalowana by dopasować się do kamery RGB. Dodatkowo dzięki tej technologii kamera znacznie lepiej radzi sobie z obiektami położonymi blisko - nie ma już efektu &quot;oślepienia&quot; czujnika podczerwieni.&amp;nbsp;&lt;/div&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbhkqVaVYN3vQkD2MGPdQ3YFP1Pk113x0bGlaHqtc88AiTiNzgGN1U_PYWvrs9SAJESy-pNkOkVNzCe5ZHerm5d_po7v6_WWcHz3fSUBVda9rWU0jaDGaRXNYF1ZhTcH5hQBFvWtnTMyE/s1600/new_kinect_depth.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;221&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbhkqVaVYN3vQkD2MGPdQ3YFP1Pk113x0bGlaHqtc88AiTiNzgGN1U_PYWvrs9SAJESy-pNkOkVNzCe5ZHerm5d_po7v6_WWcHz3fSUBVda9rWU0jaDGaRXNYF1ZhTcH5hQBFvWtnTMyE/s400/new_kinect_depth.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Rendering głębi&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Z interesujących rzeczy, to w zasadzie tyle. Pewnie wiele osób zauważyło, że zostało zaprezentowanych jeszcze kilka innych możliwości: badanie obciążenia poszczególnych kości szkieletu czy mierzenie siły uderzenia. Przyznam jednak, że (o ile nie dostaliśmy tego w zestawie z API) jesteśmy w stanie to osiągnąć korzystając z obecnej generacji sprzętu. Jedynym usprawnieniem na jakie zwróciłem uwagę to zwiększona ilość kości, dla wykrywanego szkieletu. Dalej jendak nie ma tu rewolucji - ręka zyskała drugi palec, zaś barki dodatkowe jointy. Obsługa gestów także nie została specjalnie usprawniona. &quot;Pinch to zoom&quot; w wersji dla XBoksa jest wykonalny (dość łatwo) już dziś, zaś &quot;Swipe left / right&quot; działa tak samo, jak dla aktualnej generacji (swoją drogą, reimplementując obsługę tego gestu można uzyskać znacznie lepsze wyniki, czego prototyp pokazałem &lt;a href=&quot;http://www.youtube.com/watch?v=0FRBbSOq5H4&quot; target=&quot;_blank&quot;&gt;tu&lt;/a&gt;). Zaprezentowane na koniec wykrywanie tętna gracza wydaje mi się mocno naciągane, jednak będę musiał dokładniej poznać temat by wyrobić sobie o nim zdanie. Czy to koniec narzekania? Jeszcze nie. Rzeczą która najbardziej mnie zawiodła, to ciągle słaba dokładność śledzenia szkieletu. Nie uczyniono tutaj zbyt dużego postępu, zaś &lt;a href=&quot;http://www.youtube.com/watch?v=nuVPiXetfdM&amp;amp;noredirect=1&quot; target=&quot;_blank&quot;&gt;demko&lt;/a&gt; pokazywane przez PrimeSense ponad dwa lata temu, prezentuje się w tej materii znacznie lepiej (swoja drogą nigdy nie udało mi się uzyskać tak rewelacyjnych wyników jak na owym filmiku).&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Czy jest zatem na co czekać? Moim zdaniem tak. Myślę, że do końca roku Microsoft dopracuje API oraz sterownik i część przedstawionych tu bolączek zostanie zlikwidowana. Liczę także, że konkurencja pokaże nowe wersje swoich rozwiązań. O ile PrimeSense dość mocno interesuje się rynkiem &lt;a href=&quot;http://www.youtube.com/watch?v=uz8FZp7fJKQ&quot; target=&quot;_blank&quot;&gt;mobilnym&lt;/a&gt;&amp;nbsp;(kto nie chciałby Kinecta w telefonie?)&amp;nbsp;to zwiększenie dokładności stacjonarnych wersji urządzeń, też powinno leżeć w ich interesie. Zagadką pozostaje także dostępność nowego Kinecta w wersji dla PC. Na kompatybilność z OpenNI, chyba nie mamy co liczyć.&amp;nbsp;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/05/nowy-kinect.html</link><author>noreply@blogger.com (msemegen)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWre8TCX_OwCqr0I_nex6n1pg1sMXxSr7YgZ4xoTyEPGMxglQuUg8KNYSV4WjypaZonSdYH4d_G_YWgEpPuTsqXWawKZO6GbDjC9wdWmQlAKJzZuL6nbvrp1onuIepNbYriL8GAEZFQJU/s72-c/xbox-one-kinect-sensor_1280.0_cinema_640.0.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-5585680913265875458</guid><pubDate>Wed, 24 Apr 2013 11:37:00 +0000</pubDate><atom:updated>2013-04-25T23:09:39.085+02:00</atom:updated><title>COTW - Pola i flagi bitowe w C++</title><description>Każdy pewnie korzystał z flag bitowych w C/C++. Wygodne i zgrabne narzędzie do przekazywania parametrów, które szczególnie ukochali sobie programiści Microsoftu projektujący WinApi.&lt;br /&gt;
Czasem zdarza się jednak, że przekazane kombinacje mogą być bardzo finezyjne, a parametry dla instrukcji warunkowych niekoniecznie muszą mieścić się na jednym ekranie (nazwy flag często są dość długie). W takiej sytuacji idealnym wyjściem byłoby przypisanie wyniku sumy bitowej każdej flagi do osobnej zmiennej typu&amp;nbsp;&lt;span style=&quot;background-color: white; color: blue; font-family: Consolas; font-size: 13px;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;i na niej wykonywać operacje warunkowe. Nie ma jednak nic za darmo. W najbardziej&amp;nbsp;&lt;/span&gt;pesymistycznym&lt;span style=&quot;font-family: inherit;&quot;&gt;&amp;nbsp;przypadku będziemy&amp;nbsp;&lt;/span&gt;musieli&lt;span style=&quot;font-family: inherit;&quot;&gt;&amp;nbsp;stworzyć 32 lub 64 takie zmienne i dla każdej z nich dokonać przypisania. Narzut jest dość spory. Można to rozwiązać lepiej? Można. Z pomocą przychodzą pola bitowe.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;pre style=&quot;background-position: initial initial; background-repeat: initial initial; font-family: Consolas;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&lt;stdio .h=&quot;&quot;&gt;&lt;/stdio&gt;&lt;/span&gt;
 
&lt;span style=&quot;color: blue;&quot;&gt;struct&lt;/span&gt;&amp;nbsp;Data
{
 &lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;a&amp;nbsp;:&amp;nbsp;1;
 &lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;b&amp;nbsp;:&amp;nbsp;1;
 &lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;c&amp;nbsp;:&amp;nbsp;1;
};
 
&lt;span style=&quot;color: blue;&quot;&gt;enum&lt;/span&gt;&amp;nbsp;Flags
{
 FLAG_1&amp;nbsp;=&amp;nbsp;0x1,
 FLAG_2&amp;nbsp;=&amp;nbsp;0x2,
 FLAG_3&amp;nbsp;=&amp;nbsp;0x4
};
 
&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;main()
{
 &lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;uFlags&amp;nbsp;=&amp;nbsp;FLAG_1&amp;nbsp;|&amp;nbsp;FLAG_3;
 Data&amp;nbsp;f;
 
 f&amp;nbsp;=&amp;nbsp;*((Data*)&amp;amp;uFlags);
 
 printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;,&amp;nbsp;f.a&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;&amp;nbsp;?&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;a&amp;nbsp;==&amp;nbsp;true&quot;&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;a&amp;nbsp;==&amp;nbsp;false&quot;&lt;/span&gt;);
 printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;,&amp;nbsp;f.b&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;&amp;nbsp;?&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;b&amp;nbsp;==&amp;nbsp;true&quot;&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;b&amp;nbsp;==&amp;nbsp;false&quot;&lt;/span&gt;);
 printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s\n&quot;&lt;/span&gt;,&amp;nbsp;f.c&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;&amp;nbsp;?&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;c&amp;nbsp;==&amp;nbsp;true&quot;&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;c&amp;nbsp;==&amp;nbsp;false&quot;&lt;/span&gt;);
 
 &lt;span style=&quot;color: blue;&quot;&gt;return&lt;/span&gt;&amp;nbsp;0;
}&lt;/pre&gt;
&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
Struktura&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;Data &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;przechowuje pola&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&amp;nbsp;bitowe. Każde pole zajmuje jeden bit. Ich kolejność jest zgodna z flagami enuma&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;Flags&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Dzięki przypisaniu zmiennej przechowującej flagi (&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;uFlags&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: inherit;&quot;&gt;) do owej struktury typu&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: inherit;&quot;&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;f&amp;nbsp;=&amp;nbsp;*((Data*)&amp;amp;uFlags);&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: inherit;&quot;&gt;), możemy w szybki sposób zacząć pracować z flagami bitowymi, tak samo jak ze zwykłymi zmiennymi typu logicznego.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
&lt;br /&gt;</description><link>http://msemegen.blogspot.com/2013/04/cotw-pola-i-flagi-bitiwe-w-c.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-6683399413188712782</guid><pubDate>Thu, 28 Feb 2013 15:27:00 +0000</pubDate><atom:updated>2013-02-28T16:27:55.328+01:00</atom:updated><title>Kinect dev diary - part 2</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
Tak jak obiecałem na facebooku, dziś kolejne dev diary, tym razem Kinectowe. Od pewnego czasu pracujemy nad rozwiązaniami dotyczącymi interfejsów użytkownika, dla urządzeń użytku publicznego. Podejść było bardzo dużo. Głównie chodziło o intuicyjność oraz stabilność śledzenia. Niżej możemy zobaczyć końcowy efekt. Jest jeszcze kilka rzeczy do poprawienia, jednak całość zachowuje się już dość stabilnie.&lt;br /&gt;
Warto zaznaczyć, że warstwa prezentacji jest stworzona we Flashu. Grafiki są jak najbardziej testowe - chodzi tylko o pogląd na ogólne rozwiązanie. Gest machnięcia w prawo (swipe right) został zaimplementowany przez nas. NITE udostępnia jego rozpoznawanie, jednak działało to dość losowo. &amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Klienta Flashowego stworzył Michał Prażuch.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/TIR9lWwPbyU&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;</description><link>http://msemegen.blogspot.com/2013/02/kinect-dev-diary-part-2.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/TIR9lWwPbyU/default.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-4437770010868523738</guid><pubDate>Mon, 25 Feb 2013 13:36:00 +0000</pubDate><atom:updated>2013-02-26T08:27:05.331+01:00</atom:updated><title>C++ COTW - Placement new jako memcpy</title><description>&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: blue;&quot;&gt;#include&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #990000;&quot;&gt;&amp;lt;new&amp;gt;&lt;/span&gt;
 
&lt;span style=&quot;color: blue;&quot;&gt;struct&lt;/span&gt;&amp;nbsp;Vec3d
{
    &lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;&amp;nbsp;x,y,z;
 
    Vec3d()
    {&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;        x&amp;nbsp;=&amp;nbsp;y&amp;nbsp;=&amp;nbsp;z&amp;nbsp;=&amp;nbsp;0.0f;
    }
 
    Vec3d(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;&amp;nbsp;x,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;&amp;nbsp;y,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;&amp;nbsp;z)
    {
        &lt;span style=&quot;color: blue;&quot;&gt;this&lt;/span&gt;-&amp;gt;x&amp;nbsp;=&amp;nbsp;x;
        &lt;span style=&quot;color: blue;&quot;&gt;this&lt;/span&gt;-&amp;gt;y&amp;nbsp;=&amp;nbsp;y;
        &lt;span style=&quot;color: blue;&quot;&gt;this&lt;/span&gt;-&amp;gt;z&amp;nbsp;=&amp;nbsp;z;
    }
 
};
 
&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;main()
{
 
    Vec3d&amp;nbsp;v1(1.0f,&amp;nbsp;2.0f,&amp;nbsp;3.0);
    Vec3d&amp;nbsp;v2;
 
    v2&amp;nbsp;=&amp;nbsp;(*&lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt;(&amp;amp;v2)Vec3d(v1));
 
    printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%f,&amp;nbsp;%f,&amp;nbsp;%f\n&quot;&lt;/span&gt;,&amp;nbsp;v2.x,&amp;nbsp;v2.y,&amp;nbsp;v2.z);
}&lt;/pre&gt;
&lt;br /&gt;
Kolejna część z serii Coś Of The Week, dla C++. Tym razem został pokazany dość oryginalny sposób kopiowania danych, beż użycia bibliotecznej funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;memcpy&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Wykorzystać możemy do tego operator &lt;a href=&quot;http://en.wikipedia.org/wiki/Placement_syntax&quot;&gt;placement new&lt;/a&gt;&amp;nbsp;i konstruktor kopiujący obiektu. Czy jest to wydajniejsze? Mówiąc szczerze, pomiarów nie dokonywałem, ale na pierwszy rzut oka, raczej nie. Poza tym, kod jest bardziej zagmatwany. Przydaje się to jednak wtedy, gdy nie mamy dostępu lub nie chcemy załączać nagłówków gdzie znajdują się funkcje operujące na pamięci.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
. 
</description><link>http://msemegen.blogspot.com/2013/02/c-cotw-placement-new-jako-memcpy.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7439701310544204581</guid><pubDate>Thu, 21 Feb 2013 12:59:00 +0000</pubDate><atom:updated>2013-02-21T13:59:06.914+01:00</atom:updated><title>Obsługa bramki SMS Orange w.. C++ </title><description>Ostatnio postanowiłem się pobawić nieco socketami i obsługą protokołu HTTP.&amp;nbsp;Przeglądarki&amp;nbsp;własnej pisać nie będę (przynajmniej nie w przeciągu najbliższych kilku dni), chciałem jednak nieco podglądnąć jak wygląda komunikacja serwerem a klientem z wykorzystaniem HTTP. Tak oto powstał ten niewielki programik. Możemy za jego pomocą wysłać SMSa na&amp;nbsp;dowolny&amp;nbsp;numer w Orange (jeśli&amp;nbsp;jego właściciel aktywował możliwość otrzymywania wiadomości z internetu). Nie jest tu potrzebna znajomość obsługi web-service&#39;ów czy innych baz danych. Po prostu, ściągamy stronkę gdzie znajduje się obrazek CAPTCHA, wpisujemy jego zawartość i wysyłamy odpowiednio&amp;nbsp;spreparowane zapytanie metodą POST. Nie odbyło się bez zabawy w &quot;reverse engineering&quot; - na początek trzeba podglądnąć jakie informacje wysyła przeglądarka internetowa.&amp;nbsp;&lt;div&gt;
Program miał być miał i lekki, dlatego GUI pisane w czystym WinApi (o zgrozo!). Cała część &quot;internetowa&quot; znajduje się w plikach &lt;i&gt;HTTPDriver &lt;/i&gt;oraz &lt;i&gt;HTMLParser. &lt;/i&gt;Cały chaos związany z interfejsem użytkownika, znajduje się w pliku &lt;i&gt;main.cpp&lt;/i&gt;.&lt;/div&gt;
&lt;div&gt;
Oczywiście brakuje kilka podstawowych ficzerów - mieszkanie w tray&#39;u oraz książka adresowa. To może jednak, innym razem.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
Wszelakie uwagi mile widziane.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;http://dl.dropbox.com/u/21426852/Blog/SMSGateway.zip&quot;&gt;Link do źródeł.&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6UGAWJxzJ8gP-je6b3PseXKfbnRQGlk7_qnI_O3r_uSh47IiN4g8cPQ7tvpnskOwmE7kfQ_5yd_v6c03QolQYwAx_7emzkB21dUlkFxfcmlpI15MgWPPAsb2D-qDEfSdhwQ7Ttx1L7k4n/s1600/sms.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6UGAWJxzJ8gP-je6b3PseXKfbnRQGlk7_qnI_O3r_uSh47IiN4g8cPQ7tvpnskOwmE7kfQ_5yd_v6c03QolQYwAx_7emzkB21dUlkFxfcmlpI15MgWPPAsb2D-qDEfSdhwQ7Ttx1L7k4n/s1600/sms.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/02/obsuga-bramki-sms-orange-w-c.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6UGAWJxzJ8gP-je6b3PseXKfbnRQGlk7_qnI_O3r_uSh47IiN4g8cPQ7tvpnskOwmE7kfQ_5yd_v6c03QolQYwAx_7emzkB21dUlkFxfcmlpI15MgWPPAsb2D-qDEfSdhwQ7Ttx1L7k4n/s72-c/sms.png" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8932924472998872790</guid><pubDate>Sat, 16 Feb 2013 00:34:00 +0000</pubDate><atom:updated>2013-02-16T01:34:33.573+01:00</atom:updated><title>C++ COTW (Coś Of The Week)</title><description>&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; A&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A(&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;char&lt;/span&gt; *sz)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s &quot;&lt;/span&gt;, sz);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~A()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;~A &quot;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; B&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; B(&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;char&lt;/span&gt; *sz)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s &quot;&lt;/span&gt;, sz);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~B()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;~B &quot;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; C&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C(&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;char&lt;/span&gt; *sz)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;%s &quot;&lt;/span&gt;, sz);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~C()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;~C &quot;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; App&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; App() :
a(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;A&quot;&lt;/span&gt;), b(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;B&quot;&lt;/span&gt;),
c(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;C&quot;&lt;/span&gt;) {printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;App&quot;&lt;/span&gt;);} &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C c;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; B b;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A a;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; main()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; App
m;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;\n&quot;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;\n&quot;&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;o:p&gt;Ktoś wie co pojawi się na wyjściu? Wbrew pozorom poprawną odpowiedzią będzie:&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
C B A App&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
~A ~B ~C&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Nie wierzycie? Sprawdźcie sami. Co zatem z tego wynika? Elementy na liście inicjalizacyjnej konstruktora inicjowane są przed wywołaniem samego konstruktora (co jest dość oczywiste). Dodatkowo kolejność inicjalizacji jest zgodna z kolejnością deklaracji pól w klasie. &amp;nbsp;Destrukcja zaś odbywa się od ostatniego pola.&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;</description><link>http://msemegen.blogspot.com/2013/02/c-cotw-cos-of-week.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8725794168653252483</guid><pubDate>Thu, 14 Feb 2013 13:55:00 +0000</pubDate><atom:updated>2013-02-15T20:51:44.573+01:00</atom:updated><title>Kinect - początek</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz8bQN6MdTNZKKd1RtVD9zUPvJnR8aBDBh1g9_DoNBBxJr4t61R-a-hxvT0-YN8Y0VqFv4ITtIHuXPNMhLF-VGyJ6DmOEUndo1G6cNIDhodFk0JWM6R84PnUFB0N9IKHay0hrC-yhCA0dw/s1600/openni.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;116&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz8bQN6MdTNZKKd1RtVD9zUPvJnR8aBDBh1g9_DoNBBxJr4t61R-a-hxvT0-YN8Y0VqFv4ITtIHuXPNMhLF-VGyJ6DmOEUndo1G6cNIDhodFk0JWM6R84PnUFB0N9IKHay0hrC-yhCA0dw/s320/openni.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;Tak jak obiecałem, przyszedł ten czas by zająć się Kinectem. Zainstalujemy sterowniki, zapoznamy się z ogólna architekturą API oraz napiszemy prosty programik do szpiegowania ludzi. Na wstępie jednak, kilka uwag. Nie będzie tu omawiane API od Microsoftu. Nie chodzi tu o moją niechęć do monopolistów, tylko względy praktyczne. OpenNI ma lepszą licencję, daje wsparcie dla sensorów konkurencji (ktoś ma Asusa XTion lub PrimeSense Carmine?) i działa na Linuksie. Korzystać będziemy z wersji 1.5.4, a nie z wydanej ostatnio 2.1. Nowa wersja jest wciąż w fazie beta, poza tym wprowadza bardzo duże zmiany w samej organizacji kodu i po prostu nie miałem czasu by dokładniej się nimi zająć. Dodatkowo będziemy używać interfejsu napisanego w C a nie w C++. Jakiejś specjalnej awersji do klas nie czuję, ale w tym przypadku wersja strukturalna przedstawia się znacznie czytelniej.&lt;br /&gt;
Zatem do dzieła.&lt;br /&gt;
&lt;h4&gt;
Sterowniki i architektura systemu&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;/div&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: left; margin-right: 1em; text-align: left;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpghyphenhyphen0H654zJQfkAEO8400FohqAc-TUMk8xWUjFzn3Ay00KtjdPOy_zXQ8Glbouqm4eSeKTthBPgqHol_qFJVTMEQILHk0cVbvlfBLd1covqQMecxZzTmR6QVVyELEPH2ZlOks7ulpzYsE/s1600/text4019.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;335&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpghyphenhyphen0H654zJQfkAEO8400FohqAc-TUMk8xWUjFzn3Ay00KtjdPOy_zXQ8Glbouqm4eSeKTthBPgqHol_qFJVTMEQILHk0cVbvlfBLd1covqQMecxZzTmR6QVVyELEPH2ZlOks7ulpzYsE/s400/text4019.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Architektura aplikacji zbudowanej w oparciu o OpenNI&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Wszystko składa się w zasadzie z dwóch komponentów - NITE i OpenNI. Jak widać na obrazku obok, są one ze sobą dość ściśle powiązane i szczerze mówiąc, nie mam zielonego pojęcia czym kierowali się projektanci tego systemu, tworząc go właśnie w taki sposób. Na szczęście, nigdy nie będziemy musieli się nad tym zastanawiać. Opiszmy może elementy tego diagramu. Na samym dole mamy oczywiście sprzęt wyposażony w SoC od PrimeSense. Wyżej (w kształcie litery C) jest OpenNI. Biblioteka ta dostarcza interfejsy komunikacyjne dla sterowników oraz middleware, zajmującego się analizą obrazu i głębi. W środku znajdują się dwa komponenty: NITE Algorithms oraz Sensor Data Acquisition. Pierwszy z nich odpowiada za analizę danych odbieranych z czujników, zaś &amp;nbsp;Sensor Data Acquisition, wykonuje całą robotę związaną z bezpośrednią komunikacją komputera z sensorami. Wyżej już mamy tylko NITE Controls, czyli framework odpowiedzialny za rozpoznawanie i obsługę gestów oraz aplikację końcową - to czym będziemy zajmować się my.&lt;br /&gt;
Mając omówione podstawowe elementy, możemy zająć się praktyką. Przede wszystkim potrzebujemy sterowników i SDK. Ściągniemy je klikając &lt;a href=&quot;http://www.openni.org/openni-sdk/openni-sdk-history-2/&quot;&gt;tu&lt;/a&gt; i &lt;a href=&quot;https://github.com/avin2/SensorKinect&quot;&gt;tu&lt;/a&gt;. Na początku instalujemy OpenNI SDK, zaś później pozostałe komponenty. Jeśli nie posiadamy Kinecta (lub mamy inny sprzęt) nie potrzebujemy pakietu z GitHuba.&lt;br /&gt;
Gdy wszystko przebiegnie pomyślnie, Kinect powinien zamrugać do nas zieloną diodą. Jesteśmy zatem gotowi, by okiełznać tego potwora!&lt;br /&gt;
&lt;h4&gt;
Hello world&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
Stwórzmy zatem program do lokalizowania ludzi. Gdybyśmy chcieli wykorzystać do tego kamerę i zestaw bibliotek do analizy obrazu (np. OpenCV) z pewnością byłby to bardzo dobry temat na pracę magisterską. Pomijając fakt, że musielibyśmy zadbać o odpowiednie warunki oświetleniowe oraz jakość dostarczanych danych (rozdzielczość, FPS), nadal byłaby przed nami setki linii kodu wraz z opasłymi tomiskami opisującymi różne algorytmy analizujące obraz. Tutaj zaś, mamy bezpośredni dostęp do interesujących nas danych, zaś dzięki technologii zastosowanej w Kinectcie, nie musimy martwić się o oświetlenie.&lt;br /&gt;
Na początek więc, po instalacji całego pakietu, kopiujemy SDK (folder &lt;i&gt;Include &lt;/i&gt;oraz &lt;i&gt;Lib &lt;/i&gt;z katalogu &lt;i&gt;OpenNI&lt;/i&gt;) do lokalizacji z komponentami zewnętrznymi (u nas jest to &lt;i&gt;Externals&lt;/i&gt;). Ustawiamy ścieżki i robimy resztę magii związanej z IDE. Do&lt;i&gt; main.cpp&lt;/i&gt; kopiujemy coś takiego:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;bContextReady =&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;false&lt;/span&gt;;
&lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;bDepthSensorReady =&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;false&lt;/span&gt;;
 
XnContext *pContext;
XnNodeHandle depthHandle;
 
bContextReady&amp;nbsp;=&amp;nbsp;xnInit(&amp;amp;pContext)&amp;nbsp;==&amp;nbsp;XN_STATUS_OK;
 
&lt;span style=&quot;color: blue;&quot;&gt;if&lt;/span&gt;(bContextReady&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;)
{
 bDepthSensorReady&amp;nbsp;=&amp;nbsp;xnCreateDepthGenerator(pContext,&amp;nbsp;&amp;amp;depthHandle,&amp;nbsp;NULL,&amp;nbsp;NULL)&amp;nbsp;==&amp;nbsp;XN_STATUS_OK;
}
 
&lt;span style=&quot;color: blue;&quot;&gt;if&lt;/span&gt;(bContextReady&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;bDepthSensorReady&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;)
{
 xnStartGeneratingAll(pContext);
 
 printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Sensor&amp;nbsp;started...\n&quot;&lt;/span&gt;);
 
 &lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;iRet&amp;nbsp;=&amp;nbsp;0;
 &lt;span style=&quot;color: blue;&quot;&gt;while&lt;/span&gt;(iRet&amp;nbsp;==&amp;nbsp;0)
 {
  xnWaitAnyUpdateAll(pContext);
  iRet&amp;nbsp;=&amp;nbsp;_kbhit(); 
 }
 xnProductionNodeRelease(depthHandle);
 xnContextRelease(pContext);
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;}&lt;/pre&gt;
&lt;div&gt;
Ogólna zasada działania programu jest prosta - inicjalizujemy wszystkie niezbędne zabawki, startujemy je, a później w pętli sprawdzamy stan sensorów, do których się wcześniej podłączyliśmy (w naszym przypadku jest to detektor głębi). W oczy rzucają się dwa typy:&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;XnContext &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;oraz&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;XnNodeHandle&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Kontekst to podstawowy obiekt OpenNI. Zawiera on stan całej aplikacji oraz wszystkich sensorów, do jakich podpięliśmy się podczas startu programu.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;XnNodeHandle &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;to uchwyt do obiektu, dzięki któremu uzyskujemy interesujące nas dane. Aby uzyskać dostęp do dowolnego generatora musimy zawołać funkcję&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnCreateXXX&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;, gdzie pod&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;XXX &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;możemy wstawić:&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;AudioGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;DepthGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;GestureGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;HandsGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;ImageGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;IRGenerator&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;Player&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;Recorder&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;SceneAnalizer&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;UserGenerator&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Dziś oczywiście nie będziemy zajmować się wszystkimi wyżej&amp;nbsp;&lt;/span&gt;przedstawionymi generatorami - skorzystamy tylko z ostatniego. Daje on możliwość detekcji i lokalizowania ludzi. Jego tworzenie, zgodnie z wyżej przedstawionym schematem wygląda następująco:&lt;/div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;XnNodeHandle&amp;nbsp;usersHandle;
xnCreateUserGenerator(pContext,&amp;nbsp;&amp;amp;usersHandle,&amp;nbsp;NULL,&amp;nbsp;NULL);&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
&lt;/div&gt;
Dzięki niemu będziemy mogli dowiedzieć się ile osób stoi w polu widzenia Kinecta, pobrać położenie ich geometrycznego środka lub dowiedzieć się, czy dany piksel transmitowanego obrazu należy do &lt;a href=&quot;http://msemegen.blogspot.com/2013/01/kinect-dev-diary-part-1.html&quot;&gt;określonej osoby&lt;/a&gt;&amp;nbsp;(choć można to zrobić również za pomocą analizatora sceny).&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
Każdy aktor (bądź użytkownik, wedle nomenklatury OpenNI) posiada własny ID. Maksymalnie możemy wykryć do piętnastu osób. Wejście aktora na scenę (obszar widoczny przez Kinecta) wiąże się z automatycznym powiązaniem go z konkretnym numerem. ID jest zwalnianie wtedy gdy aktor zniknie ze sceny na dłużej niż pięć sekund. Jest to bardzo przydatne, bo chwilowe utracenie osoby nie oznacza wykrycia jej jako nowego użytkownika. Bardzo ładnie to widać na &lt;a href=&quot;http://www.youtube.com/watch?v=KcxdmeHqYyI&quot;&gt;tym video&lt;/a&gt;. Przypatrzmy się zatem w jaki sposób możemy zaimplementować proste liczenie ludzi:&lt;/div&gt;
&lt;div&gt;
&lt;pre style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;USERS_BUFFER_LENGTH =&amp;nbsp;15;
XnUserID&amp;nbsp;users[USERS_BUFFER_LENGTH];&lt;/pre&gt;
&lt;pre style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;iRet&amp;nbsp;=&amp;nbsp;0;
&lt;span style=&quot;color: blue;&quot;&gt;while&lt;/span&gt;(iRet&amp;nbsp;==&amp;nbsp;0)
{&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt; &lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;short&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;uUsersCount  =&amp;nbsp;USERS_BUFFER_LENGTH;
 &lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;short&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;uVisibleUsersCount =&amp;nbsp;0;
 
 xnWaitAnyUpdateAll(pContext);
 
 memset(users,&amp;nbsp;0x0,&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(users));
 xnGetUsers(usersHandle,&amp;nbsp;users,&amp;nbsp;&amp;amp;uUsersCount);
 
 &lt;span style=&quot;color: blue;&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;uUsersCount;&amp;nbsp;i++)
 {
  XnPoint3D&amp;nbsp;com;
  xnGetUserCoM(usersHandle,&amp;nbsp;users[i],&amp;nbsp;&amp;amp;com);
 
  &lt;span style=&quot;color: blue;&quot;&gt;if&lt;/span&gt;(com.Z&amp;nbsp;&amp;gt;&amp;nbsp;0.0f)
  {
   uVisibleUsersCount++;
  }
 }
 
 printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Users&amp;nbsp;count:&amp;nbsp;%d\r&quot;&lt;/span&gt;,&amp;nbsp;uVisibleUsersCount);
 
 iRet&amp;nbsp;=&amp;nbsp;_kbhit();
}&lt;/pre&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
Co my tu mamy. Przede wszystkim tworzymy bufor, w którym możemy przechować identyfikatory. Kluczową jest tutaj funkcja&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnGetUsers&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Przyjmuje ona uchwyt do generatora, wskaźnik na bufor oraz maksymalną liczbę elementów które mogą zostać zapisane. Przekazujemy tą zmienna przez wskaźnik, bo zwracana jest w niej rzeczywista ilość wykrytych ludzi. W pętli iterującej przez wszystkie elementy bufora&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;users &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;pobieramy pozycję każdej wykrytej osoby (&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnGetUserCoM - &lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;i&gt;Get User Center Of Mass&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: inherit;&quot;&gt;). Zastanawiający jest tylko warunek, sprawdzający, czy współrzędna z jest większa od zera. Jak już wspominałem wcześniej, OpenNI przechowuje ID aktora, do pięciu sekund od jego zniknięcia ze sceny. Po tym, gdy aktor zejdzie ze sceny i jest ciągle w buforze jego pozycja z jest właśnie ustawiana na zero.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white; font-family: inherit;&quot;&gt;Ostatnią rzeczą o której chciałbym opowiedzieć to magiczna metoda&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnWaitAnyUpdateAll&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Jak sama nazwa wskazuje, służy ona do aktualizacji danych, pochodzących z interesujących nas sensorów. Jest jednak cała rodzina tego typu funkcji:&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnWaitAnyUpdateAll&lt;/span&gt; - czeka aż dowolny z detektorów zgłosi, że ma nowe dane. Jeśli tak, reszta detektorów jest automatycznie aktualizowana&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnWaitOneUpdateAll&lt;/span&gt; - czeka aż jeden detektor (którego uchwyt przekazany jest w argumencie) zgłosi, że ma nowe dane. Jeśli tak, reszta detektorów jest automatycznie aktualizowana&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnWaitAndUpdateAll&lt;/span&gt; - czeka aż wszystkie detektory będą miały nowe dane i dopiero wtedy je aktualizuje&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;xnNoneUpdateAll&lt;/span&gt; - nie czeka na żaden z detektorów, tylko automatycznie aktualizuje wszystkie dostępne&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;To w zasadzie tyle. Wyświetlanie dokładnej pozycji przechodzących ludzi zostawiam na zadanie domowe. Nie będzie to trudne, tym bardziej, że mamy już wszystkie potrzebne informacje. Solucje można pobrać &lt;a href=&quot;https://dl.dropbox.com/u/21426852/Blog/1%20-%20Kinect.zip&quot;&gt;tu&lt;/a&gt;. &amp;nbsp;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/02/kinect-poczatek.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz8bQN6MdTNZKKd1RtVD9zUPvJnR8aBDBh1g9_DoNBBxJr4t61R-a-hxvT0-YN8Y0VqFv4ITtIHuXPNMhLF-VGyJ6DmOEUndo1G6cNIDhodFk0JWM6R84PnUFB0N9IKHay0hrC-yhCA0dw/s72-c/openni.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-2715868708731114983</guid><pubDate>Wed, 06 Feb 2013 10:19:00 +0000</pubDate><atom:updated>2013-02-06T11:19:45.086+01:00</atom:updated><title>STM&#39;owe pamiętniki</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
Dziś będzie krótko, jak zwykle mało efektownie, ale treściwie. Ostatnio, mając chwilkę wolnego czasu, usiadłem do STM&#39;a i udało się machnąć niewielkie demko. Pokazana jest tam komunikacja evala z komputerem PC, za pomocą portu COM. Za pomocą klawiatury możemy sterować&amp;nbsp;czterema&amp;nbsp;diodami, umieszczonymi na płytce. Do komunikacji po stronie PC potrzebny jest terminal dający możliwość połączenia po porcie RS232 (np. Tera Term). Któregoś wieczora machnę jeszcze jakiś niewielki dedykowany program do obsługi ledów, zaś za jakiś czas uwolnimy tkwiący w płytce port USB. W drodze są już kolejne odcinki kursu kodowania na tego zwierzaka.&amp;nbsp;&lt;/div&gt;
Źródła dostępne są &lt;a href=&quot;https://dl.dropbox.com/u/21426852/Blog/STM324F_UART.zip&quot;&gt;tu&lt;/a&gt;. Wszystkie najważniejsze pliki są w katalogu głównym projektu. Na koniec krótka demonstracja:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/TJNrDgUmUsk?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/02/stmowe-pamietniki.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-9011078298712934938</guid><pubDate>Sun, 03 Feb 2013 02:13:00 +0000</pubDate><atom:updated>2013-02-03T03:13:39.601+01:00</atom:updated><title>OpenGL, część druga</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
Dziś będziemy kontynuować naszą przygodę z malowaniem, tudzież rysowaniem. Po ostatnich wywodach pewnie każdy wie jak poprawnie trzymać pędzel w ręku. Dziś w końcu będziemy mogli &amp;nbsp;uwolnić nasz talent i stworzyć nasze pierwsze, wielkie dzieło - &quot;Hello world&quot;.&lt;br /&gt;
&lt;h4&gt;
Wierzchołki i indeksy&lt;/h4&gt;
&lt;div&gt;
W świecie OpenGL&#39;a podstawowym&amp;nbsp;budulcem wyświetlanych obiektów są &lt;b&gt;wierzchołki&lt;/b&gt;. Za ich pomocą możemy namalować pojedynczy punkt, linię oraz trójkąt. W naszym przypadku nawet koło będzie składać się ze skończonej liczby elementów, choć w grafice dwuwymiarowej niekoniecznie musi to być prawdą. Jak było wspomniane w poprzedniej &lt;a href=&quot;http://msemegen.blogspot.com/2013/01/pedzle-w-don.html&quot;&gt;notce&lt;/a&gt;, wierzchołek składa się &amp;nbsp;z atrybutów. Podstawowym atrybutem jaki musi mieć każdy wierzchołek to jego pozycja, w lokalnym układzie współrzędnych modelu. Zazwyczaj jest to wektor czterowymiarowy (&lt;i&gt;x, y, z, w&lt;/i&gt;). Ostatnia współrzędna nie jest jawnie używana. Potrzebna jest ona do przekształceń macierzowych i koniec końców, ustawiamy jej wartość na jeden. Dodatkowo wierzchołek może mieć kolor (np. &lt;i&gt;r, g, b, a&lt;/i&gt;) lub informacje o położeniu tekstury - &lt;i&gt;texcoord&lt;/i&gt;, przekazywane jako wektor&amp;nbsp;dwuwymiarowy.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
Wszystko co będziemy renderować, będzie stworzone z trójkątów - jednego z trzech wyżej wymienionych prymitywów. Każdy model, we współczesnych grach trójwymiarowych, jest obiektem stworzonym z &amp;nbsp;dużej liczby trójboków. Dzieje się tak dlatego, że dostępne dziś na rynku układy graficzne, zoptymalizowane są właśnie do pracy z trójkątami. Nawet gdy będziemy operować na zwykłych sprite&#39;ach, znanych choćby z biblioteki SDL, to dalej dla nas będą to wieloboki - choć znacznie prostsze. &amp;nbsp;&lt;/div&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: left; margin-right: 1em; text-align: left;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHSpX7H_xMGrf3ANsll3mtxn1nLEx6MRsk5CzI3R_gV0gKjL6uWFiAx14XDFMpHhCZ_0dJ81Vp5PNQSizV_UI-8WoeCtu7Iw7OgFi3NW60dKntqXfKr6HcI96sOELBT7NOTyhyyIHSX33/s1600/text3768.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;177&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHSpX7H_xMGrf3ANsll3mtxn1nLEx6MRsk5CzI3R_gV0gKjL6uWFiAx14XDFMpHhCZ_0dJ81Vp5PNQSizV_UI-8WoeCtu7Iw7OgFi3NW60dKntqXfKr6HcI96sOELBT7NOTyhyyIHSX33/s200/text3768.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Kolejność przeciwna do ruchu&amp;nbsp;wskazówek&lt;br /&gt;
&amp;nbsp;zegara (&lt;i&gt;counterclockwise direction; CCW&lt;/i&gt;)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
Tutaj przechodzimy do kilku podstawowych kwestii technicznych. Przede wszystkim &lt;b&gt;kolejność ułożenia wierzchołków&lt;/b&gt;: zgodna lub przeciwna z ruchem wskazówek zegara. Dlaczego ma to znaczenie? W grę wchodzą zagadnienia optymalizacyjne. Mając konkretnie zdefiniowaną kolejność, możemy określić przednią oraz tylną stronę wielokąta i renderować tylko jedną z nich (zazwyczaj przednią). Domyślnym trybem jest ten &amp;nbsp;pokazany na rysunku obok - przeciwny do ruchów wskazówek zegara. Oczywiście możemy go zmienić. &lt;br /&gt;
&lt;div style=&quot;text-align: right;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtHZ55lT1wzFxMaReDTUVuuihXPWcPPv0IWS9XEc4F41b7VQKsn46hOynVpV2AlLDKd0gqK2sAGAOg8WWAjiyyAkvlbU9WQ9-z32sk2syXZTZT1N-zCt3eEz-TCJFKv4RHmdVHfsXMb6zP/s1600/text3768-7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;170&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtHZ55lT1wzFxMaReDTUVuuihXPWcPPv0IWS9XEc4F41b7VQKsn46hOynVpV2AlLDKd0gqK2sAGAOg8WWAjiyyAkvlbU9WQ9-z32sk2syXZTZT1N-zCt3eEz-TCJFKv4RHmdVHfsXMb6zP/s200/text3768-7.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Indeksowanie wierzchołków&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Pozostaje jeszcze jedna wątpliwość - sam &lt;b&gt;proces budowania prymitywów z wierzchołków&lt;/b&gt;. Rozważmy prosty przykład - prostokąt. Jest to wielokąt składający się z&amp;nbsp;czterech&amp;nbsp;wierzchołków. Aby go wyświetlić jednak potrzebujemy dwóch trójkątów, czyli o dwa wierzchołki więcej. Dla małych modeli taka nadmiarowość ma niewielkie znaczenie, jednak dla wirtualnych środowisk składających się z milionów wielokątów, może być to poważny narzut danych. Jak sobie z tym poradzić? Stosując indeksację. Wystarczy, że do funkcji renderującej przekażemy dwie informacje: samą listę wierzchołków oraz trójki indeksów wierzchołków, budujących trójkąty. Brzmi lekko skomplikowanie, ale w rzeczywistości jest to bardzo proste. Popatrzmy na rysunek obok. Mamy tam przedstawiony kwadrat składający się &amp;nbsp;z dwóch trójkątów i czterech wierzchołków. Wierzchołki dwa i cztery są wspólne dla obu prymitywów. Pierwszy trójkąt zatem będzie się składał z wierzchołków o numerach: zero, jeden i dwa, zaś drugi budują wierzchołki dwa, trzy i zero. To w zasadzie wszystko. Mając te informacje, możemy budować geometrię dla naszych lokacji.&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Tablice wierzchołków i indeksów&amp;nbsp;&lt;/h4&gt;
&lt;div&gt;
Pokodujmy więc chwilę. Na początek zdefiniujmy wszystkie niezbędne typy:&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; Vec4d&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt; x, y, z, w;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; ColorRGB&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt; r, g, b;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt; Vertex&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; Vec4d
position;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; ColorRGB
color;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;Face&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;short&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;v0, v1, v2;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Jak widać, nasz wierzchołek posiada dwa atrybuty: czterowymiarową pozycję i kolor. Dodatkowym typem jest&amp;nbsp;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;Face.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Struktura ta będzie odpowiedzialna za przechowywanie indeksów wielokąta (jak to bywa w C, indeksujemy od zera). Możemy zatem zająć się tworzeniem i ładowaniem geometrii. Przykładem niech będzie wspomniany wcześniej kwadrat. Tablica wierzchołków i indeksów, może być dla niego zdefiniowana następująco:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;Vertex
vertices[] =&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: green; font-family: Consolas; font-size: 9.5pt;&quot;&gt;/* x, y, z, w,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r,
g, b */&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; {0.5f,
0.5f, 1.0f, 1.0f,&amp;nbsp;&amp;nbsp; 0.0f, 0.0f, 1.0f},&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; {-0.5f,
0.5f, 1.0f, 1.0f,&amp;nbsp; 0.0f, 1.0f, 0.0f},&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; {-0.5f,
-0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f},&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp; {0.5f,
-0.5f, 1.0f, 1.0f,&amp;nbsp; 0.0f, 0.0f, 0.0f}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;Face
faces[] = &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;{0,
1, 2},&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;{2,
3, 0}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
Myślę, że przedstawiony wyżej kod jest w miarę oczywisty. Współrzędne wierzchołków podajemy w lokalnym dla modelu, układzie współrzędnych.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Malujemy!&lt;/span&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Czas na główny gwóźdź programu, czyli renderowanie.&amp;nbsp;&lt;/span&gt;Malować będziemy w pętli głównej przed podmianą buforów. Jak to zwykle bywa, wyświetlanie składać się będzie z kilku krótkich kroków.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glEnableClientState(GL_VERTEX_ARRAY);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glEnableClientState(GL_COLOR_ARRAY);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glVertexPointer(4, GL_FLOAT, &lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex), vertices);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glColorPointer(3, GL_FLOAT,&amp;nbsp; &lt;span style=&quot;color: blue;&quot;&gt;sizeof&lt;/span&gt;(Vertex),
(&lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt;*)(vertices) + 4);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
faces);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glDisableClientState(GL_VERTEX_ARRAY);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;glDisableClientState(GL_COLOR_ARRAY);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNPeI2v_94CXDzsM9HFQj7V2xYrklJCbRkVk9QX3VJJW7g2BPxRP-zJGhKxIEbNemmRuqQB15RjBNnvL64dePkOXldGlO1OwUhp0wWpPFUcWua-jAudYRYO3X9qvm4_71cCrMHR-mHJvZx/s1600/render.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;262&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNPeI2v_94CXDzsM9HFQj7V2xYrklJCbRkVk9QX3VJJW7g2BPxRP-zJGhKxIEbNemmRuqQB15RjBNnvL64dePkOXldGlO1OwUhp0wWpPFUcWua-jAudYRYO3X9qvm4_71cCrMHR-mHJvZx/s320/render.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Wynik działania programu&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Funkcja&amp;nbsp;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;glEnableClientState &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;informuje maszynę stanów OpenGL, z jakiego typu tablic będziemy korzystać. Stała&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;GL_VERTEX_ARRAY &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;może być nieco myląca, bo nie odnosi się do wierzchołka jako takiego, lecz tylko do jego pozycji. Przekazując&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;GL_COLOR_ARRAY &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;odblokowujemy możliwość renderowania kolorowych vertexów. Następne dwie funkcje (&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;glVertexPointer &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;oraz&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;glColorPointer&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;) pokazują lokalizacje tablic z pozycją i kolorem wierzchołka. Dlaczego mówię tu o tablicach? Bo dla OpenGL&#39;a są to w zasadzie dwie tablice. Nic nie stoi na przeszkodzie, by także z naszego punktu widzenia były to dwie oddzielne zmienne, jednak z powodów edukacyjnych zostaniemy przy tym rozwiązaniu. Także w przyszłości, gdy poznamy już bufory wierzchołków i indeksów, będziemy stosować takie podejście. Parametry przyjmowane przez obie funkcje są takie same. Na początek podajemy liczbę komponentów składających się na pozycję (&lt;i&gt;x, y, z, w&lt;/i&gt; - 4) i kolor (&lt;i&gt;r, g, b&lt;/i&gt; - 3). Następnie przekazujemy typ użyty do ich reprezentacji. W naszym przypadku jest to&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 13px;&quot;&gt;float &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;(stała&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;GL_FLOAT&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;). I&lt;/span&gt;&lt;span style=&quot;line-height: 18px;&quot;&gt;nne możliwe to:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;GL_SHORT&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;GL_INT&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;oraz&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&amp;nbsp;GL_DOUBLE&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Kolejny parametr pokazuje jak daleko (w bajtach) oddalone są od siebie analogiczne parametry, w określonej tablicy. Jeśli dla pozycji i kolorów chcielibyśmy użyć dwóch oddzielnych tablic, parametr ten miałby wartość zero. Dane byłby wówczas upakowane ściśle obok siebie. Gdy jednak, tablica zawiera więcej informacji, przekazujemy wielkość wierzchołka w bajtach. Ostatni parametr to wskaźnik na zerowy element danej tablicy.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: start;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;oszliśmy w końcu do malowania - funkcja&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px;&quot;&gt;glDrawElements&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Wyrenderuje ona dla nas indeksowaną geometrię. Na wstępie przekazujemy typ rysowanych prymitywów - trójkąty. Jeśli chcielibyśmy zobaczyć punkty&lt;/span&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;przekazalibyśmy&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt; line-height: 115%; text-align: justify;&quot;&gt;GL_POINTS&lt;/span&gt;&lt;span style=&quot;line-height: 115%; text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;, zaś dla linii &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt; line-height: 115%; text-align: justify;&quot;&gt;GL_LINES&lt;/span&gt;&lt;span style=&quot;line-height: 18px; text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Kolejny parametr to liczba wierzchołków do wyświetlenia, zaś&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;GL_UNSIGNED_SHORT&lt;/span&gt;&lt;span style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt; to typ danych użytych jako nasze indeksy wierzchołków (&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas; font-size: 9.5pt; text-align: justify;&quot;&gt;unsigned&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt; text-align: justify;&quot;&gt; &lt;span style=&quot;color: blue;&quot;&gt;char&lt;/span&gt; -
GL_UNSIGNED_BYTE, &lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; - GL_UNSIGNED_INT&lt;/span&gt;&lt;span style=&quot;text-align: justify;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;). Ostatni parametr to wskaźnik na indeksy. Jeszcze tylko blokujemy (&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;glDisableClientState&lt;/span&gt;&lt;span style=&quot;font-family: inherit; text-align: justify;&quot;&gt;) możliwość używania tablic pozycji i koloru wierzchołka.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;I to tyle. Naszym oczom powinien ukazać się piękny, wielokolorowy kwadrat (a w zasadzie prostokąt, ale o tym następnym razem). &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
Solucja do pobrania &lt;a href=&quot;http://dl.dropbox.com/u/21426852/Blog/2%20-%20OpenGL.zip&quot;&gt;tu&lt;/a&gt;.&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;margin-bottom: 0.0001pt;&quot;&gt;
&lt;span style=&quot;font-family: Consolas; font-size: 9.5pt;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/02/opengl-czesc-druga.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHSpX7H_xMGrf3ANsll3mtxn1nLEx6MRsk5CzI3R_gV0gKjL6uWFiAx14XDFMpHhCZ_0dJ81Vp5PNQSizV_UI-8WoeCtu7Iw7OgFi3NW60dKntqXfKr6HcI96sOELBT7NOTyhyyIHSX33/s72-c/text3768.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-4369103742456640964</guid><pubDate>Wed, 30 Jan 2013 21:48:00 +0000</pubDate><atom:updated>2013-01-30T23:47:44.985+01:00</atom:updated><title>Hello STM32</title><description>Tym razem opuścimy luksusowy świat systemów operacyjnych, grafiki wspomaganej sprzętowo i nieograniczonej, chronionej pamięci. Pożegnamy wygodę oferowaną przez szybkie wielordzeniowe procesory i znaną każdemu architekturę x86 lub x64. Dziś będzie mowa o STM32F4 i w najbliższych notkach pokażę, jak wykorzystać go do kilku niecnych rzeczy.&lt;br /&gt;
&lt;h4&gt;
Z czym to się je ?&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLK_4HueSF04x7t5Q4qDKcIRvpA3S3L31i6rr93KhYNbWqEqSTI4eLiZXveX68Cl9ZBqGGXnkQbOoTNYtx4aUd5_kwN4MtQcmgqhxwxlqA3FBuQOyX9mMJO1_U_bmVolOJKQl62ETr443U/s1600/621698_411454555580209_117390199_o.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLK_4HueSF04x7t5Q4qDKcIRvpA3S3L31i6rr93KhYNbWqEqSTI4eLiZXveX68Cl9ZBqGGXnkQbOoTNYtx4aUd5_kwN4MtQcmgqhxwxlqA3FBuQOyX9mMJO1_U_bmVolOJKQl62ETr443U/s400/621698_411454555580209_117390199_o.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Właśnie, czym jest to magiczne urządzenie? W zasadzie jest to w pełni wyposażony komputer, uzupełniony o kilka dodatkowych peryferiów. Przede wszystkim na pokładzie znajdziemy procesor ARM (Cortex M4) pracujący z częstotliwością 168 MHz. Dodatkowym atutem jest tutaj także jednostka FPU, sprzętowo wspomagająca obliczenia na liczbach zmiennoprzecinkowych. Pamięci RAM nie mamy dużo - do 192 kB (zależnie od wersji urządzenia). Na pokładzie znajdziemy jeszcze DSP, akcelerometr, mikrofon, wyjście audio, SDIO (&lt;i&gt;Secure Digital Card Input/Output&lt;/i&gt;), USB, UART, cztery programowalne diody led i przycisk. Dodatkowo masa złącz GPIO (&lt;i&gt;General Purpose Input/Output&lt;/i&gt;). Całość w bardzo przystępnej &lt;a href=&quot;http://www.kamami.pl/index.php?ukey=product&amp;amp;productID=185132&quot;&gt;cenie&lt;/a&gt;. Nic tylko brać i programować!&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Narzędzia&lt;/h4&gt;
&lt;div&gt;
Żeby móc komunikować się z evalem (i jednocześnie go zasilić), potrzebujemy kabla mini USB (nie mylić z mikro). Niestety, nie jest on dołączany do zestawu. Na szczęście płytka wyposażona jest w programator (ST-LINK/V2), więc nie jesteśmy narażeni na dodatkowe koszta. Sterowniki do niego, można ściągnąć &lt;a href=&quot;http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/SW_DRIVER/st-link_v2_usbdriver.zip&quot;&gt;tu&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
Zostało zatem wybranie IDE. Wybór mamy bardzo szeroki, ja jednak skupię się tylko na jednym - &lt;a href=&quot;http://www.coocox.org/CooCox_CoIDE.htm&quot;&gt;CooCox&lt;/a&gt;. Jest to darmowe, oparte na Eclipsie środowisko, z wbudowanym debugerem i bezpośrednią możliwością programowania płytki. Do naszych celów wystarczy w zupełności. Musimy także zaopatrzyć się w dedykowane &lt;a href=&quot;https://launchpad.net/gcc-arm-embedded/+download&quot;&gt;GCC&lt;/a&gt;. Pozostaje nam więc tylko instalacja i krótki kurs pilotażu.&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Pierwsze kroki&lt;/h4&gt;
&lt;div&gt;
Mając wszystko przygotowane, możemy wnieść trochę więcej życia, w ten skostniały sprzęt. Po instalacji wszystkich wyżej wymienionych programów, uruchamiamy CoIDE. Naszym oczom ukaże się znana sylwetka Eclipsowego środowiska. Przechodzimy do menu &lt;b&gt;Project&lt;/b&gt;. Wybieramy &lt;b&gt;Select Toolchain Path&lt;/b&gt; i tam wklejamy ścieżkę do folderu &lt;i&gt;bin&lt;/i&gt;, pakietu GCC (domyślnie jest to &lt;i&gt;C:\Program Files\GNU Tools ARM Embedded\4.7 2012q4\bin&lt;/i&gt;). Następnie tworzymy nowy projekt, korzystając z przycisku na ekranie powitalnym. Podajemy nazwę projektu a później chip na którym bazowany jest eval - STM32F4x (gdzie &lt;i&gt;x&lt;/i&gt; oznacza konkretną rewizję urządzenia, opisaną na procesorze). Kolejnym krokiem będzie wybranie komponentów. Z dostępnej listy zaznaczamy &lt;b&gt;RCC&lt;/b&gt;. Automatycznie powinny dodać się &lt;b&gt;CMSIS BOOT&lt;/b&gt; oraz &lt;b&gt;M4 CMSIS Core&lt;/b&gt;. Do tego dodajemy jeszcze &lt;b&gt;GPIO &lt;/b&gt;i jesteśmy gotowi by uruchomić pierwszy program. W liście plików (dodanych automatycznie podczas wyboru komponentów) znajdujemy &lt;b&gt;main.cpp &lt;/b&gt;i wklejamy poniższy kod:&lt;br /&gt;
&lt;pre style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;#include &lt;/span&gt;&lt;span style=&quot;color: #cc0000; font-family: Consolas;&quot;&gt;&quot;stm32f4xx.h&quot;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;
#include &lt;/span&gt;&lt;span style=&quot;color: #cc0000; font-family: Consolas;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #cc0000; font-family: Consolas;&quot;&gt;stm32f4xx_gpio.h&quot;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;
#include &lt;/span&gt;&lt;span style=&quot;color: #cc0000; font-family: Consolas;&quot;&gt;&quot;stm32f4xx_rcc.h&quot;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;

&lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;GPIO_InitTypeDef  GPIO_InitStructure;&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;

void &lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;delay(&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;volatile unsigned int &lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;uTime)&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;
    while&lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;((uTime--) &amp;gt; 0)
    {
    }
}&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;

void &lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;main(&lt;/span&gt;&lt;span style=&quot;color: blue; font-family: Consolas;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;font-family: Consolas;&quot;&gt;)
{

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &amp;amp;GPIO_InitStructure);

    &lt;span style=&quot;color: blue;&quot;&gt;while&lt;/span&gt;(1)
    {
        GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
        delay(100000);

        GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
        delay(100000);

        GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
        delay(100000);

       GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
       delay(100000);
    }
}&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;text-align: start;&quot;&gt;&lt;/pre&gt;
Po kompilacji (&lt;i&gt;Project -&amp;gt; Build&lt;/i&gt; albo &lt;i&gt;F7&lt;/i&gt;) i wlaniu softu na płytkę (&lt;i&gt;Flash -&amp;gt; Program Download&lt;/i&gt;), nasz STM powinien pociesznie zamrugać do nas swoimi wszystkimi kolorowymi diodami.&lt;br /&gt;
Następnym razem zajmiemy się dokładną analizą powyższego przykładu. Tymczasem to tyle.&lt;br /&gt;
Solucja, a właściwie workspace, do pobrania &lt;a href=&quot;http://dl.dropbox.com/u/21426852/Blog/1%20-%20STM32.zip&quot;&gt;tu&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/01/hello-stm32.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLK_4HueSF04x7t5Q4qDKcIRvpA3S3L31i6rr93KhYNbWqEqSTI4eLiZXveX68Cl9ZBqGGXnkQbOoTNYtx4aUd5_kwN4MtQcmgqhxwxlqA3FBuQOyX9mMJO1_U_bmVolOJKQl62ETr443U/s72-c/621698_411454555580209_117390199_o.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8433095220284303890</guid><pubDate>Tue, 29 Jan 2013 11:30:00 +0000</pubDate><atom:updated>2013-01-30T19:42:54.904+01:00</atom:updated><title>Kinect dev diary - part 1</title><description>&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Od dziś, co jakiś czas będę zamieszczał krótkie demka, z postępów prac nad kilkoma aplikacjami, które mam przyjemność tworzyć. Jako, że większość czasu spędzam walcząc z Kinectem, więc zamieszczane tu materiały będą w znacznym procencie dotyczyć właśnie tej technologii.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Na pierwszy ogień poszła segmentacja aktorów widocznych na scenie oraz wyświetlenie ich bez tła. Jak widać na poniższym filmiku, jest tam jeszcze kilka niedokładności. Wystarczy jednak końcowy efekt poddać &amp;nbsp; obróbce (np. w OpenCV) by całość wyglądała bardziej znośnie. Działanie programu jest nieczułe na warunki oświetleniowe, więc sylwetka człowieka byłaby dalej widoczna w warunkach całkowitej ciemności. Z tyłu nie ma żadnego blue box&#39;a czy innego screena. Po prostu, aplikacja potrafi odróżnić człowieka od otaczających go obiektów. Oczywiście za jakiś czas opiszę, jak samemu coś takiego stworzyć.&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/-d4V2oDkyko?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/01/kinect-dev-diary-part-1.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-5563973791496839643</guid><pubDate>Sun, 27 Jan 2013 01:00:00 +0000</pubDate><atom:updated>2013-01-27T02:00:14.163+01:00</atom:updated><title>Pędzle w dłoń!</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL8RmJOx78dXSmrlhz6R9FjxPszOyQmK9Pkryt0ztVVNqq-pWg0o-uQgBpXiNiEL5pBJKRkEgDiKa2K0R_bfDowDSQ8qwF-OIruqVe52IbHDkb64uYi82KejfDrGMuH4398lWVb5NVzbIq/s1600/opengl1.jpeg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;102&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL8RmJOx78dXSmrlhz6R9FjxPszOyQmK9Pkryt0ztVVNqq-pWg0o-uQgBpXiNiEL5pBJKRkEgDiKa2K0R_bfDowDSQ8qwF-OIruqVe52IbHDkb64uYi82KejfDrGMuH4398lWVb5NVzbIq/s200/opengl1.jpeg&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;Dziś będzie o malowaniu. Robić to będziemy w OpenGL&#39;u do spółki z GLSL&#39;em.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Pierwszą rzeczą o jaką musimy zadbać, to zaopatrzyć się w dwie&amp;nbsp;biblioteki: &amp;nbsp;&lt;a href=&quot;http://www.glfw.org/&quot; target=&quot;_blank&quot;&gt;GLFW&lt;/a&gt;&amp;nbsp;i &lt;a href=&quot;http://glew.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;GLEW&lt;/a&gt;. Pierwsza z nich będzie odpowiadać za tworzenie okna, kontekstu oraz obsługę wejścia. Robi to ona dla trzech wiodących systemów operacyjnych, więc gdy będziemy chcieli nasz kod opublikować w wersji dla Linuxa czy OS X&#39;a, nie będziemy musieli zbyt wiele grzebać w kodzie (przynajmniej teoretycznie). GLEW zaś, ma za zadanie ułatwić pracę z rozszerzeniami, z którymi jak wiadomo, jest mały problem na platformie Microsoftu.&lt;/div&gt;
&lt;h4&gt;
Rozkładamy sztalugi&amp;nbsp;&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Mając przygotowane wszystkie narzędzia bierzemy się do pracy. Jako, że&amp;nbsp;wspominanie&amp;nbsp;wcześniej&amp;nbsp;biblioteki&amp;nbsp;są niewielkich rozmiarów możemy ich źródła dodać do solucji. Pierwszą rzeczą jaką będziemy musieli wykonać to utworzenie okna, po którym będziemy mogli machać pędzlem. Zrobi to za nas funkcja 
&lt;span style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;glfwOpenWindow&lt;/span&gt;. Przyjmuje ona kilka parametrów. Pierwsze dwa określają rozmiary okna. Następnie przekazujemy liczbę bitów na każdy kanał koloru (&lt;i&gt;red, green, blue&lt;/i&gt;) i przezroczystości (&lt;i&gt;alpha&lt;/i&gt;). Kolejnymi parametrami jest liczba bitów jakie chcemy przeznaczyć na bufor głębi oraz &lt;a href=&quot;http://pl.wikipedia.org/wiki/Bufor_szablonowy&quot; target=&quot;_blank&quot;&gt;szablonu&lt;/a&gt;&amp;nbsp;(&lt;i&gt;stencil buffer&lt;/i&gt;). Na końcu przekazujemy informacje o trybie pracy okna - pełnoekranowym lub okienkowym. Zanim jednak utworzymy okno, będziemy musieli zainicjować cały subsystem, wołając bezargumentową funkcję&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glfwInit&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 13px;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Po&amp;nbsp;wykonaniu&amp;nbsp;powyższych operacji możemy przejść do pętli głównej, która jest sercem naszej aplikacji. W niej będzie wykonywało się wyświetlanie, odczytywanie stanu wejścia a także cała logika gry lub symulacji. Jak to zwykle bywa w tego typu aplikacjach, będzie to pętla nieskończona, przerywana na życzenie użytkownika. Tym życzeniem będzie po prostu wyjście z programu.&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;bool&lt;/span&gt;&amp;nbsp;bRun&amp;nbsp;=&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;;
&lt;span style=&quot;color: blue;&quot;&gt;while&lt;/span&gt;(bRun&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;)
{
    glfwSwapBuffers();
    bRun&amp;nbsp;=&amp;nbsp;(glfwGetWindowParam(GLFW_OPENED)&amp;nbsp;==&amp;nbsp;GL_TRUE)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(glfwGetKey(GLFW_KEY_ESC)&amp;nbsp;==&amp;nbsp;GLFW_RELEASE);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Mamy więc kilka tajemniczych linii kodu. Pierwsza z wywoływanych funkcji (&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px; text-align: justify;&quot;&gt;glfwSwapBuffers&lt;/span&gt;) odpowiada za podmianę buforów (&lt;a href=&quot;http://pl.wikipedia.org/wiki/Podw%C3%B3jne_buforowanie&quot; target=&quot;_blank&quot;&gt;podwójne buforowanie&lt;/a&gt;) i obsługę zdarzeń związanych z działaniem naszego okna. Linijkę niżej jest podejmowana decyzja o dalszym życiu naszej aplikacji. W pierwszej części wyrażenia sprawdzamy czy okno nadal jest widoczne, zaś w drugiej czy klawisz Escape jest puszczony. Jeśli oba te warunki są spełnione, możemy działać dalej. Jeśli zmienna 
&lt;span style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;bRun&amp;nbsp;&lt;/span&gt;przyjmie wartość&amp;nbsp;&lt;span style=&quot;background-color: white; color: blue; font-family: Consolas; font-size: 13px;&quot;&gt;false&lt;/span&gt;, będzie to oznaczać, że czas życia naszego programu dobiegł końca. Żeby poprawnie zakończyć pracę i pozbierać za sobą wszystkie zabawki musimy wywołać funkcję&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;glfwTerminate&lt;/span&gt;. Uprzątnie&amp;nbsp;ona za nas cały bałagan który przed chwilą stworzyliśmy. Całość&amp;nbsp;prezentuje&amp;nbsp;się następująco:&lt;br /&gt;
&lt;pre style=&quot;background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt;&amp;nbsp;main()
{
&lt;span style=&quot;color: blue;&quot;&gt;    bool&lt;/span&gt;&amp;nbsp;bReady&amp;nbsp;=&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;false&lt;/span&gt;;
    bReady&amp;nbsp;=&amp;nbsp;(glfwInit()&amp;nbsp;==&amp;nbsp;GL_TRUE);
 
&lt;span style=&quot;color: blue;&quot;&gt;    if&lt;/span&gt;(bReady&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;)
    {
        glfwOpenWindow(800,&amp;nbsp;600,&amp;nbsp;8,&amp;nbsp;8,&amp;nbsp;8,&amp;nbsp;8,&amp;nbsp;32,&amp;nbsp;32,&amp;nbsp;GLFW_WINDOW);
 
&lt;span style=&quot;color: blue;&quot;&gt;        bool&lt;/span&gt;&amp;nbsp;bRun&amp;nbsp;=&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;;
&lt;span style=&quot;color: blue;&quot;&gt;        while&lt;/span&gt;(bRun&amp;nbsp;==&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;)
        {
            glfwSwapBuffers();
            bRun&amp;nbsp;=&amp;nbsp;(glfwGetWindowParam(GLFW_OPENED)&amp;nbsp;==&amp;nbsp;GL_TRUE)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(glfwGetKey(GLFW_KEY_ESC)&amp;nbsp;==&amp;nbsp;GLFW_RELEASE);
        }
 
        glfwTerminate();
    }
&lt;span style=&quot;color: blue;&quot;&gt;    return&lt;/span&gt;&amp;nbsp;0;
}&lt;/pre&gt;
&lt;h4&gt;
Dobieramy farby&lt;/h4&gt;
Mając gotową obsługę okna, możemy zająć się malowaniem. Tutaj warto zatrzymać się nad kilkoma aspektami technicznymi. Przede wszystkim nie będą opisane tu przestarzałe funkcje z rodziny &lt;i&gt;fixed pipeline&lt;/i&gt;. &amp;nbsp;Po drugie, wersja OpenGL&#39;a, którą będziemy używać to 2.0. Dlaczego nie nowsza? Końcowy plan jest taki, by kod renderujący, który tutaj stworzymy, przenieść na platformę mobilną (jak będę bogaty będzie to iOS, jeśli spłacę długi będzie to Android, a jeśli żadna z tych rzeczy się nie wydarzy - bada), gdzie niepodzielnie rządzi OpenGL ES 2.0, który jest kompatybilny (pomijając pewne niuanse) z omawianą tu wersją desktopową.&lt;br /&gt;
Skoro mamy to już wyjaśnione, porozmawiajmy trochę o &lt;b&gt;shaderach&lt;/b&gt;. Ten magiczny stwór, to nic innego jak program uruchamiany na karcie graficznej. Jego nazwa (&lt;i&gt;program cieniujący&lt;/i&gt;) może być nieco myląca, ponieważ nie odpowiada on tylko za cieniowanie i oświetlenie. Język GLSL jest na tyle elastyczny, że możemy w nim stworzyć praktycznie dowolny efekt.&lt;br /&gt;
&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;float: right; margin-left: 1em; text-align: right;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioS2jqn2_OaPfibCFLJZ-xNhmsssCh5GJLagzRwky_HJ42I7zpu5uhdIq7A2it9CD1suoQ0DblDOkOK3V1QCmQdqu1sr86VnI7ZRbffbG6pMEgV6Ns4AeZrHLk0AsXYY18K68u1GzITlZ9/s1600/pipeline.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;225&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioS2jqn2_OaPfibCFLJZ-xNhmsssCh5GJLagzRwky_HJ42I7zpu5uhdIq7A2it9CD1suoQ0DblDOkOK3V1QCmQdqu1sr86VnI7ZRbffbG6pMEgV6Ns4AeZrHLk0AsXYY18K68u1GzITlZ9/s400/pipeline.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://goanna.cs.rmit.edu.au/~gl/teaching/Interactive3D/2012/lecture2.html&quot; target=&quot;_blank&quot;&gt;Źródło&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Podstawowym kryterium podziału shaderów jest ich przeznaczenie - wierzchołki (&lt;i&gt;vertex shaders&lt;/i&gt;) i fragmenty (&lt;i&gt;fragment shaders&lt;/i&gt;). &amp;nbsp;Fragmenty, to nic innego jak piksele. Możemy zatem wykonywać operacje na wierzchołkach jak i na pojedynczych pikselach. Kolejność wykonywania shaderów, wraz z resztą funkcji potoku renderowania zastała przedstawiona na obrazku obok.&lt;br /&gt;
Zobaczmy zatem jak wygląda GLSL. Jest on bardzo zbliżony do C. Posiada trochę więcej typów oraz kilka wbudowanych zmiennych (prefiks&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;gl_&lt;/span&gt;).&lt;br /&gt;
Jak na porządny język programowania przystało, całość zaczyna się od funkcji&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;main&lt;/span&gt;. Jest bezargumentowa i nie zwraca nic. Wynik działania shadera zapisywany jest w zmiennych wyjściowych. W naszym przypadku dla wierzchołków ich obliczoną pozycję będziemy przekazywać do&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;gl_Position&lt;/span&gt;, zaś ostateczny kolor piksela zapisywać w&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;gl_FragColor&lt;/span&gt;. Obie zmienne są typu&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;vec4&lt;/span&gt; (x,y,z,w). Komunikacja na linii aplikacja - shader odbywa się za pomocą &lt;b&gt;uniformów&lt;/b&gt;. Są to specjalne zmienne, których adres możemy pobrać za pomocą funkcji udostępnianych przez API OpenGL&#39;a, a następnie ustawić je na konkretne wartości. Dodatkowo do dyspozycji mamy także &lt;b&gt;atrybuty wierzchołków&lt;/b&gt;. Są to dane, które opisują wierzchołek (kolor, pozycja w układzie współrzędnych modelu, texcoord) i nie zmieniają się zbyt często. Możliwa jest także rozmowa pomiędzy vertex i fragment shaderem. Wystarczy, że w obu źródłach stworzymy zmienną, o tej samej nazwie oraz typie i dodamy jej modyfikator&amp;nbsp;&lt;span style=&quot;background-color: white; font-family: Consolas; font-size: 13px;&quot;&gt;varying&lt;/span&gt;. Wówczas wartość przypisana do tej zmiennej w shaderze wierzchołków, będzie widoczna w shaderze fragmentów. &lt;br /&gt;
Pozostała jeszcze ostatnia rzecz - kompilacja i linkowanie. Każdy program, nawet ten uruchamiany na GPU, musi zostać skompilowany. Będziemy to robić w czasie działania aplikacji, za pomocą odpowiednich funkcji OpenGL. Vertex oraz fragment shadery kompilowane są osobno, jednak ostatecznie linkowane są w jeden program.&lt;br /&gt;
To tyle na dziś. Znów było teoretyczne przynudzanie. Następnym razem przedstawię bufory wierzchołków, wspólnie popełnimy pierwszy shader i wspomnę coś o matmie.&lt;br /&gt;
Tradycyjnie, solucja do pobrania &lt;a href=&quot;https://dl.dropbox.com/u/21426852/Blog/1%20-%20OpenGL.zip&quot;&gt;tu&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/01/pedzle-w-don.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL8RmJOx78dXSmrlhz6R9FjxPszOyQmK9Pkryt0ztVVNqq-pWg0o-uQgBpXiNiEL5pBJKRkEgDiKa2K0R_bfDowDSQ8qwF-OIruqVe52IbHDkb64uYi82KejfDrGMuH4398lWVb5NVzbIq/s72-c/opengl1.jpeg" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-280759846035673601</guid><pubDate>Tue, 22 Jan 2013 19:51:00 +0000</pubDate><atom:updated>2013-01-22T20:51:43.146+01:00</atom:updated><title>Kinect - wprowadzenie</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg06eSZuGMLQSWXZ8ZNZhgoZrIFyPii_FBWFNZHjX22Slh81To0koMFD22k1PNwUbOqMYLfnIm7p7SnHrN2jRU-NiXzfsZAYqeN3pW-JSOxSLFnkG4DHt4BeFFcGEbI_ugseK0FxmmskODQ/s1600/kinect.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; display: inline !important; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;244&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg06eSZuGMLQSWXZ8ZNZhgoZrIFyPii_FBWFNZHjX22Slh81To0koMFD22k1PNwUbOqMYLfnIm7p7SnHrN2jRU-NiXzfsZAYqeN3pW-JSOxSLFnkG4DHt4BeFFcGEbI_ugseK0FxmmskODQ/s320/kinect.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;Dziś &amp;nbsp;o programowaniu będzie niewiele. Za to będziemy skakać, biegać, machać rękami i robić masę różnych, nieprzyjemnych rzeczy. Będziemy zatem gadać o Kinect&#39;cie.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Microsoft przedstawił swój kontroler w 2010 roku, na targach E3. Początkowo miał on służyć tylko do grania i sterowania konsolą Xbox 360, jednak zorganizowana grupa ciekawskich internautów dobrała się do intymnych części urządzenia.&amp;nbsp;Niedługo&amp;nbsp;później światło dzienne ujrzały filmiki prezentujące lepiej lub gorzej zrealizowane aplikacje, wykorzystujące ukryty potencjał owej zabawki. Microsoft jednak nie reagował zbytnio na te rewelacje. Być może dlatego, że urządzenie do końca nie jest to ich&amp;nbsp;wynalazkiem&amp;nbsp;tylko izraelskiej firmy &lt;a href=&quot;http://www.primesense.com/&quot; target=&quot;_blank&quot;&gt;PrimeSense&lt;/a&gt;, o której będę wspominał pewnie nie raz. Koniec końców mały/miękki wypuścił SDK pracujące z systemem Windows, drugą wersję kontrolera, przeznaczoną tylko dla PC, oraz niezwykle poruszającą &lt;a href=&quot;http://vimeo.com/31744508&quot; target=&quot;_blank&quot;&gt;reklamówkę&lt;/a&gt;.&lt;br /&gt;
Co na to PrimeSense? Nie próżnowali i wypuścili swoją wersję SDK. Nazwali ją OpenNI (NI -&amp;nbsp;&lt;i&gt;natural interaction&lt;/i&gt;), zbudowali aktywną społeczność i sprawili, że Kinect zaczął rozmawiać z Linuxem i Mac OS&#39;em. Dodatkowo OpenNI działa nie tylko z urządzeniem Microsoftu. Jeśli nie lubimy monopolistów możemy zaopatrzyć się w odpowiedni sensor bezpośrednio u PrimeSense lub u Asusa (XTion).&lt;br /&gt;
Czymże zatem jest Kinect? Prawdę mówiąc jest to skaner 3D, wyposażony w dodatkową logikę i SDK. W zastawie znajdziemy&amp;nbsp;również&amp;nbsp;kamerkę RGB, kilka mikrofonów, akcelerometr (!) oraz silniczek krokowy. Wszystko po to, by móc poskakać na wirtualnym pontonie.&lt;br /&gt;
Trójwymiarowe widzenie zapewnia Kinectowi promiennik podczerwieni, który rzuca siatkę punktów na obiekty znajdujące się w zasięgu jego widzenia. Dodatkowa kamera, widząca tylko w wąskim zakresie podczerwieni, analizuje ich pozycje i na tej podstawie określany jest przybliżony model 3D środowiska. Dlaczego przybliżony? Głównie przez rozdzielczość głębi - tylko 320x200. Ostatecznie jest to reskalowane do 640x480 (w takiej rozdzielczości widzi kamera RGB), jednak ciągle musimy walczyć z masą szumów, które zostają w końcowym sygnale. Spora część magii wykonuje się po stronie sterownika i samego OpenNI. Niesamowite algorytmy, których tajników pewnie nigdy nie poznam, dokonują takich operacji jak wykrywanie ludzi, &amp;nbsp;gestów czy tworzenie wirtualnych szkieletów. W naszej gestii zostaje tylko wykorzystanie tego potencjału. Nie ma jednak nic za darmo. Operowanie na chmurze punktów jest dość kosztowne obliczeniowo. Oczywiście bardzo wiele zależy od aplikacji, ale absolutnym minimum jest procesor dwurdzeniowy - cztery rdzenie mile widziane.&lt;br /&gt;
Zastosowanie podczerwieni ma też wady. Pierwszą z nich, jest ślepota sensora głębi w jasno oświetlonych pomieszczeniach. Wyprowadzanie Kinecta na spacer w słoneczne dni, nic nie da - nie zobaczy zbyt dużo. Urządzenie ma także problem z widzeniem czarnych rzeczy lub ciemnoskórych osób, choć to zależy także od panujących wokoło warunków oświetleniowych.&lt;br /&gt;
Najbardziej interesującą zaletą Kinecta jest jego sprawne działanie w całkowitej ciemności. Co prawda, w tym przypadku kamera RGB zda się na niewiele, jednak widzenie możemy przełączyć na podczerwień, która jest pięknie oświetlona przez promiennik. Sprawność pozostałych możliwości związanych z wykrywaniem ludzi i gestów zostaje zachowana.&lt;br /&gt;
Rzeczą która niezwykle ułatwia testowanie aplikacji, jest możliwość wykorzystania nagrań imitujących sygnał z sensorów kontrolera. Wstawanie od biurka i gimnastykowanie się przed urządzeniem z logiem Microsoftu, dla wielu programistów może być mało komfortowe. Możemy zatem uniknąć dziwnych spojrzeń kolegów z pracy, nagrywając wcześniej kilka sekund, za pomocą wcześniej przygotowanej aplikacji.&lt;br /&gt;
No cóż, to w zasadzie tyle. Dokładniejszą specyfikację techniczną Kinecta znajdą Państwo w internecie. Następnym razem może coś pokodujemy, choć nie obiecuję - sama instalacja sterowników, to niezły temat na notkę. Serio.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/01/kinect-wprowadzenie.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg06eSZuGMLQSWXZ8ZNZhgoZrIFyPii_FBWFNZHjX22Slh81To0koMFD22k1PNwUbOqMYLfnIm7p7SnHrN2jRU-NiXzfsZAYqeN3pW-JSOxSLFnkG4DHt4BeFFcGEbI_ugseK0FxmmskODQ/s72-c/kinect.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7847934584412810971</guid><pubDate>Sat, 19 Jan 2013 17:09:00 +0000</pubDate><atom:updated>2013-02-03T11:46:30.042+01:00</atom:updated><title>Box2D - czyli pierwsze starcie z fizyką</title><description>&lt;div&gt;
Wymagania:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;SVN&lt;/li&gt;
&lt;li&gt;Visual C++ 2010&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div align=&quot;justify&quot; style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Dziś nikt nie będzie rozmawiał o wzorach, równaniach i innych wyprowadzeniach. Tym zajęli się inni, a my skorzystamy z ich ciężkiej pracy.&lt;br /&gt;Tytułowy Box2D, to silnik fizyczny autorstwa Erina Catto, przeznaczony do symulowania fizyki ciał sztywnych w świecie dwuwymiarowym. &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Aktualnie jest on najlepszym tego typu narzędziem. Możemy także wykorzystać bardziej zaawansowane rozwiązania typu Havok czy PhysX, jednak przekonanie ich do współpracy z naszą dwuwymiarową rzeczywist&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;ością wymaga trochę pracy. Poza tym, omawiana tu biblioteka jest najczęściej wykorzystywanym rozwiązaniem problemu symulacji &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;w grach 2D. Na zachętę dodam, że samo Angry Birds zostało napisane w oparciu o Boxa2D. &lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;h4 style=&quot;text-align: justify;&quot;&gt;
Przygotowanie środowiska&amp;nbsp;&lt;/h4&gt;
&lt;div align=&quot;justify&quot; style=&quot;text-align: justify;&quot;&gt;
Jak &lt;span style=&quot;font-family: inherit;&quot;&gt;nieśmiało wspomniałem na początku&lt;/span&gt;, korzystać będziemy z Visual Studio 2010 (&lt;a href=&quot;http://www.microsoft.com/visualstudio/plk/downloads#d-2010-express&quot;&gt;link&lt;/a&gt; do wersji Express). Samą bibliotekę checkout&#39;ujemy korzystając z repozytorium na serwerach Google (&lt;a href=&quot;http://box2d.googlecode.com/svn/trunk/&quot;&gt;http://box2d.googlecode.com/svn/trunk/&lt;/a&gt;). Gdy źródła będą już na naszym dysku (w tym tutorialu wykorzystuję rewizję nr 251) możemy przekopiować je do naszej solucji i zacząć tworzenie pierwszej, prostej symulacji.&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Tworzymy świat&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Każda symulacja fizyczna składa się &amp;nbsp;z dwóch podstawowych elementów - świata oraz ciał, których ruch mode&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;lowa&lt;/span&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;ny jest w jego obręb&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;ie. E&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;lementy takie jak jointy, sensory czy motory są elementami działającymi bezpośrednio na ciała i służą do określonej zmiany zachowań obiektów. Ich użycie pokazane będzie w następnych częściach kursu.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Pierwszą rzeczą którą musimy stworzyć jest więc świat. Jedyną informacją którą będziemy przekazywać&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt; podczas jego konstrukcji &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;jest grawitacja wyrażona jako wektor siły.&lt;/span&gt;&lt;/div&gt;
&lt;pre align=&quot;justify&quot; style=&quot;background-attachment: scroll; background-clip: border-box; background-color: white; background-image: none; background-origin: padding-box; background-position: 0% 0%; background-repeat: repeat; background-size: auto; color: black; font-family: &amp;quot;Consolas&amp;quot;; font-size: 13px;&quot;&gt;b2World&amp;nbsp;*pWorld&amp;nbsp;=&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; b2World(b2Vec2(0.0f, -9.8f));&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Warto zaznaczyć, że typ przekazanego wektora to&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2Vec2&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Jak nazwa wskazuje, jest to wektor dwuwymiarowy, zawierający pola&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;x
&lt;/span&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt; oraz &lt;/span&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Istnieje kilka wariantów jego konstrukcji, posiada także szereg przydatnych metod - ciekawskich odsyłam do pliku &lt;i&gt;b2Math.h&lt;/i&gt;&lt;/span&gt;. Stworzyliśmy zatem świat, którego grawitacja jest analogiczna do naszej ziemskiej.&lt;/div&gt;
&lt;h4&gt;
Niech się stanie ruch&lt;/h4&gt;
Plac zabaw został zatem zbudowany. Czas zainwestować w zabawki. Pierwszą rzeczą jaką musimy zrobić to odpowiednie wypełnienie struktury &lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2BodyDef&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Zawiera ona wszystkie niezbędne informacje, które musi znać silniki fizyki przed stworzeniem nowego obiektu. Oto kilka podstawowych:&lt;/span&gt;

&lt;br /&gt;
&lt;ul&gt;&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;
&lt;li&gt;b2BodyType type&lt;/li&gt;
&lt;li&gt;b2Vec2 position&lt;/li&gt;
&lt;li&gt;float32 angle&lt;/li&gt;
&lt;li&gt;b2Vec2 linearVelocity&lt;/li&gt;
&lt;li&gt;float32 angularVelocity&lt;/li&gt;
&lt;/span&gt;&lt;/ul&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Tworzone ciało może być dynamiczne (&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2_dynamicBody&lt;/span&gt;), kinematyczne (&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2_kinematicBody&lt;/span&gt;) lub statyczne (&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2_staticBody&lt;/span&gt;). &lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Obiekty dynamiczne będą najczęściej przez nas wykorzystywane. Poddają się one każdym aspektom symulacji oraz kolidują ze wszystkimi fizycznymi elementami świata. Mają niezerową masę.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Obiekty kinematyczne nie są poddawane efektom działających na nie sił, mogą się jednak poruszać poprzez przyłożenie im prędkości. Nie kolidują z innymi ciałami kinematycznymi lub statycznymi. Mają nieskończoną masę (~0).&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ciała statyczne nie podlegają symulacji ruchu. Można je przesuwać, poprzez manualną zmianę ich pozycji, ale z wielu względów nie jest to zalecane. Podobnie jak obiekty kinematyczne mają nieskończoną masę oraz nie kolidują ze sobą.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Początkowa pozycja i kąt (w radianach) to następne elementy struktury. Podajemy je we współrzędnych świata. Warto zaznaczyć tu, że jak na porządny silnik fizyki przystało, Box2D operuje jednostkami systemu MKS. Każdy kto miał fizykę w podstawówce pewnie wie jak rozwinąć ten skrót. Dlatego, jeśli projektujemy naszą grę i zdecydujemy się na wykorzystanie fizyki, podstawową jednostkę gry nie mogą być piksele (200 pikselowy obiekt będzie mieć 200 metrów).&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Jeśli chcemy by po stworzeniu obiekt poruszał się ustawiamy wektor prędkości liniowej lub kątowej.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Bardziej ciekawskie osoby, zapoznają się pewnie z całością struktury &lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2BodyDef&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;, której pełną definicję można znaleźć w pliku &lt;i&gt;b2Body.h&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;. Mając wyjaśnione wszystkie podstawowe zagadnienia, możemy w końcu dodać ciało do świata:&lt;/span&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;b2BodyDef bodyDefinition;
 
bodyDefinition.type            = b2_dynamicBody;
bodyDefinition.position        = b2Vec2(0.0f, 3.0f);
bodyDefinition.angle           = 0.0f;
bodyDefinition.linearVelocity  = b2Vec2_zero;
bodyDefinition.angularVelocity = 0.1f;
 
b2Body *pFirstBody = pWorld-&amp;gt;CreateBody(&amp;amp;bodyDefinition);
&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
I cóż my tu mamy. Na samym początku wypełnianie wyjaśnionych wcześniej elementów struktury. Następnie zaś obiekt dodawany jest do świata. Gdy operacja zakończy się powodzeniem, otrzymujemy wskaźnik na ciało.&lt;/div&gt;
&lt;h4&gt;
Let&#39;s play&lt;/h4&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Czas wiec uruchomić machinę i wystartować animację. Obliczanie równań ruchu będziemy przeprowadzać co klatkę, dla ustalonego kroku czasowego, który powinien być stały (&lt;a href=&quot;http://gafferongames.com/game-physics/fix-your-timestep/&quot; target=&quot;_blank&quot;&gt;Fix your timestep!&lt;/a&gt;). Musimy podać też liczbę iteracji dla solvera, którego działanie podzielone jest na dwie fazy: wyliczania prędkości i pozycji. Więcej informacji o jego działaniu możemy znaleźć w &lt;a href=&quot;http://box2d.org/manual.pdf&quot; target=&quot;_blank&quot;&gt;manualu&lt;/a&gt;. Z naszego punktu widzenia istotna jest informacja, że im większa liczba iteracji, tym symulacja jest dokładniejsza, jednak tracimy na wydajności. Trzeba zatem wypracować złoty środek, który zależy jednak od konkretnego projektu.&lt;/div&gt;
&lt;pre style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; uVelocityIterations = 8;
&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; uPositionIterations = 6;
 
pWorld-&amp;gt;Step(1.0f / 60.0f, uVelocityIterations, uPositionIterations);&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Uruchamiamy zatem naszą symulację z prędkością sześćdziesięciu klatek na sekundę (na razie czysto teoretycznie) z odpowiednią liczbą iteracji dla poszczególnych faz. Teraz przydałaby się informacja na temat położenia naszego ciała. Uzyskujemy ją wołając metodę&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;GetPosition()&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt; dla utworzonego ciała. Zwraca ona wektor dwuwymiarowy. Metoda&amp;nbsp;&lt;/span&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;GetAngle() &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;zwraca aktualny kąt w radianach. I to w zasadzie wszystko. Całość prezentuje się następująco:&lt;/span&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; uVelocityIterations = 8;
&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; uPositionIterations = 6;
 
&lt;span style=&quot;color: blue;&quot;&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; uFramesCount = 60;
&lt;span style=&quot;color: blue;&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color: blue;&quot;&gt;unsigned&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; i = 0; i &amp;lt; uFramesCount; i++)
{
    pWorld-&amp;gt;Step(1.0f / 60.0f, uVelocityIterations, uPositionIterations);
 
    b2Vec2 position = pFirstBody-&amp;gt;GetPosition();
    &lt;span style=&quot;color: blue;&quot;&gt;float&lt;/span&gt; fAngle    = pFirstBody-&amp;gt;GetAngle();
 
    printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Position&amp;nbsp;x:&amp;nbsp;%.3f,&amp;nbsp;y:&amp;nbsp;%.3f\n&quot;&lt;/span&gt;, position.x, position.y);
    printf(&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;Angle:&amp;nbsp;%.3f\n&quot;&lt;/span&gt;, fAngle);
}&lt;/span&gt;&lt;/pre&gt;
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Na sam koniec traktujemy wskaźnik&lt;/span&gt;&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt; pWorld &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;operatorem&lt;/span&gt; 
&lt;span style=&quot;background: white; color: black; font-family: Consolas; font-size: 13;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;delete&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;No cóż, efekt na razie mizerny, ale nikt cudów nie obiecywał. W następnych częściach pogadam trochę o integracji fizyki z OpenGLem. Mam nadzieję, że nikt po drodze nie zasnął.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Solucję do tej części można pobrać &lt;a href=&quot;https://dl.dropbox.com/u/21426852/Blog/1%20-%20Box2D.zip&quot; target=&quot;_blank&quot;&gt;tu&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;</description><link>http://msemegen.blogspot.com/2013/01/box2d-czyli-pierwsze-starcie-z-fizyka.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3601334900660882450</guid><pubDate>Fri, 18 Jan 2013 14:58:00 +0000</pubDate><atom:updated>2013-01-19T18:32:27.364+01:00</atom:updated><title>I&#39;m back</title><description>&lt;div style=&quot;text-align: justify;&quot;&gt;
Minęło sporo czasu od ostatniego wpisu. Krótka przerwa przerodziła się w długą nieobecność. Jestem jednak z powrotem w wielkim świecie blogerów i wiele wskazuje na to, że następne wpisy będą ukazywać się w miarę regularnie. O czym zatem będę zrzędzić? Pogadam trochę o dwuwymiarowej fizyce w wykonaniu&amp;nbsp;biblioteki Box2D. Napomknę pewnie o OpenGL w zastosowaniu nie tylko na desktopy. Sporo miejsca poświęcę Kinectowi, z którym od pewnego czasu nie mogę się rozstać. Zdarzy się pewnie, że opowiem coś o embedded biorąc sobie za platformę STM32F4 a całość okraszę niezwykle&amp;nbsp;przydatnymi radami początkującego programisty C++. &lt;br /&gt;
Jeśli starczy mi&amp;nbsp;młodzieńczego&amp;nbsp;zapału poświęcę kilka notek muzyce, filmom na nawet książkom, które (wbrew obiegowej opinii) zdarza mi się przeczytać. No cóż, to na razie tyle. Nie liczcie na wiele, choć czegokolwiek możecie się spodziewać.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Tymczasem, do następnej notki. &amp;nbsp;&lt;/div&gt;
</description><link>http://msemegen.blogspot.com/2013/01/im-back.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3650362302040859888</guid><pubDate>Fri, 16 Oct 2009 23:12:00 +0000</pubDate><atom:updated>2009-10-17T10:41:07.609+02:00</atom:updated><title>Krótka przerwa</title><description>Chciałbym z przykrością poinformować, że na okres kilku najbliższych miesięcy będę musiał wstrzymać to niezwykłe i interesujące zajęcie jakim jest blogowanie (sam proces nic nierobienia w tym względzie, praktykuję już od jakiegoś czasu). Powody jako takie są. Studia (ok, tu żartuję) a także kilka innych pomniejszych / powiększych spraw, które mimo wszystko są ważniejsze i bardziej czasochłonne. Myślę, że nikt się wiec nie obrazi. Obiecuję, że za jakiś czas pojawi się coś ciekawego, tak w ramach rekompensaty. 
Nie będę bawił się w ceregiele związane z usuwaniem bloga - niech sobie wisi w czeluściach internetu. A nuż/widelec coś/komuś się przyda - no w końcu kilka notek napisałem na trzeźwo. Na serio, to szkoda mi tych 1,22 z VAT, które wydałem na domenę. 

No koniec tego bezwładnego sypania literkami po ekranie. 

Do zobaczenia :)</description><link>http://msemegen.blogspot.com/2009/10/krotka-przerwa.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7370822158091946321</guid><pubDate>Tue, 11 Aug 2009 10:08:00 +0000</pubDate><atom:updated>2009-08-12T11:15:35.219+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">assembler</category><category domain="http://www.blogger.com/atom/ns#">c++</category><title>SSE w klasie - #2</title><description>&lt;p&gt;Po omówieniu podstaw związanych z programowaniem przy użyciu instrukcji SIMD, czas przedstawić nieco bardziej użyteczne informacje. Dzisiejszym daniem głównym więc, będzie niewielka (rozwijana w kolejnych częściach mini kursu) klasa czterowymiarowego wektora. Życzę smacznego i zapraszam do lektury :). &lt;/p&gt;

&lt;p&gt;Na początku zaczniemy od przygotowania składników. Dziś zamiast wyrównanej do szesnastu bajtów tablicy typu &lt;span style=&quot;color: maroon&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;float&lt;/font&gt;&lt;font face=&quot;Verdana&quot; color=&quot;#000000&quot;&gt;, skorzystamy ze struktury:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;__declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;))
&lt;span style=&quot;color: maroon&quot;&gt;struct &lt;/span&gt;VectorData{
    &lt;span style=&quot;color: maroon&quot;&gt;float &lt;/span&gt;x,y,z,w;
};&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;p&gt;&lt;font face=&quot;Verdana&quot;&gt;Dla instrukcji SSE liczy się tak naprawdę odpowiednio przygotowany skrawek pamięci – w jaki sposób zostanie on zaalokowany (czy to będzie tablica czy struktura) zależy tylko od preferencji programisty. &lt;/font&gt;&lt;/p&gt;

&lt;font face=&quot;Verdana&quot;&gt;Mając wszystko przygotowane, możemy przejść do przyrządzania dania głównego. Na pierwszy ogień pójdzie więc konstruktor domyślny, w którym to będziemy zerować współrzędne wektora. &lt;br /&gt;Samo zerowanie jest oczywiście sprawą trywialną, choć początkowo może przysporzyć nieco problemów. &lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;Tradycyjnie, można to zrobić na dwa sposoby:&lt;/font&gt;
&lt;font face=&quot;Verdana&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;pre class=&quot;code&quot;&gt;&lt;font face=&quot;Verdana&quot;&gt;“manualne” przypisanie zer&lt;/font&gt;&lt;/pre&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;font face=&quot;Verdana&quot;&gt;skorzystanie z instrukcji&lt;/font&gt;&lt;font face=&quot;Courier New&quot;&gt; memset&lt;/font&gt; &lt;font face=&quot;Verdana&quot;&gt;(nagłówek&lt;/font&gt; &lt;font face=&quot;Courier New&quot;&gt;cstring&lt;/font&gt; &lt;font face=&quot;Verdana&quot;&gt;lub&lt;/font&gt; &lt;font face=&quot;Courier New&quot;&gt;string.h&lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;)&lt;/font&gt;
    &lt;/li&gt;
  &lt;/ul&gt;

&lt;font face=&quot;Verdana&quot;&gt;Skorzystanie z &lt;font face=&quot;Courier&quot;&gt;memset&lt;/font&gt; powinno nieco przyśpieszyć tą prostą operację, ponieważ nie odwołujemy się do koprocesora, tylko operujemy danymi bezpośrednio w pamięci. Mimo iż w konstruktorze nie potrzebujemy wyjątkowej wydajności (jest on wykonywany zazwyczaj tylko raz), to jednak wykorzystamy trochę mocy :). &lt;/font&gt;

  &lt;pre class=&quot;code&quot;&gt;&lt;font face=&quot;Verdana&quot;&gt;Otóż i niezwykle wyrafinowana treść naszej funkcji: &lt;/font&gt;&lt;/pre&gt;

  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    mov esi,&lt;span style=&quot;color: maroon&quot;&gt;this
    &lt;/span&gt;movaps xmm0,[esi]
    xorps xmm0,xmm0
    movaps [esi],xmm0
}&lt;/pre&gt;

  &lt;font face=&quot;Verdana&quot;&gt;Jak widzimy, są tu dwie nowe rzeczy. Pojawił się wskaźnik&lt;/font&gt; &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;this&lt;/font&gt; &lt;font face=&quot;Verdana&quot;&gt;oraz instrukcja&lt;/font&gt; &lt;font face=&quot;Courier New&quot;&gt;xorps&lt;/font&gt;.&lt;br /&gt;&lt;font face=&quot;Verdana&quot;&gt;Wskaźnik&lt;/font&gt; &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;this&lt;/font&gt; &lt;font face=&quot;Verdana&quot;&gt;używany jest by dostać się to struktury przechowującej wektor. Zadziała to jednak tylko wtedy gdy zmienna ta będzie pierwszym polem klasy. Wówczas adres na który wskazuje &lt;font face=&quot;Courier&quot; color=&quot;#800000&quot;&gt;this&lt;/font&gt; jest równoznaczny z adresem owego pola. &lt;br /&gt;W przeciwnym wypadku, pobranie adresu trzeba będzie wykonać “ręcznie”:&lt;/font&gt;
  &lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;*p = &amp;amp;m_vecData

&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    mov esi,p
    &lt;span style=&quot;color: gray&quot;&gt;//...
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Cóż takiego robi instrukcja &lt;/font&gt;&lt;font face=&quot;Courier New&quot;&gt;xorps&lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;? Jest to nic innego jak zwykły &lt;a href=&quot;http://pl.wikipedia.org/wiki/Alternatywa_wykluczająca&quot;&gt;xor&lt;/a&gt;, w wersji dla SSE, działający na poszczególnych elementach naszego wektora. Wykonując tą operację na dwóch takich samych wektorach, zerujemy je. Jest to znacznie szybsze, niż “statyczne” przypisanie wartości zero do każdej ze współrzędnych. &lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;Mając konstruktor domyślny, możemy stworzyć konstruktor kopiujący oraz operator przypisania. Praktycznie rzecz ujmując będą to dwie identyczne funkcje. Ich działanie będzie się tylko ograniczać do kopiowania wartości pomiędzy rejestrami xmm. Spójrzmy więc jak to wygląda:&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    mov edi,vec
    mov esi,&lt;span style=&quot;color: maroon&quot;&gt;this

    &lt;/span&gt;movaps xmm0,[esi]
    movaps xmm1,[edi]

    movaps xmm0,xmm1

    movaps [esi],xmm0
}&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;font face=&quot;Verdana&quot;&gt;Zakładam, że &lt;/font&gt;&lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;vec,&lt;/font&gt; &lt;font face=&quot;Verdana&quot; color=&quot;#000000&quot;&gt;to stała referencja na obiekt naszej klasy, przekazana do konstruktora kopiującego bądź operatora przypisania. &lt;br /&gt;Działanie, jak już wspominałem, jest bardzo proste. Rejestry &lt;font face=&quot;Courier New&quot;&gt;edi&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;esi&lt;/font&gt; przechowują wskaźniki na nasze obiekty, które następnie (za pomocą &lt;font face=&quot;Courier New&quot;&gt;movaps&lt;/font&gt;) kopiowane są do odpowiednich rejestrów SSE – &lt;font face=&quot;Courier New&quot;&gt;xmm0&lt;/font&gt; dla naszego wektora oraz &lt;font face=&quot;Courier New&quot;&gt;xmm1&lt;/font&gt; dla wektora przekazanego w parametrze. Przypisanie wektorów to po prostu skopiowanie zawartości &lt;font face=&quot;Courier New&quot;&gt;xmm1&lt;/font&gt; do &lt;font face=&quot;Courier New&quot;&gt;xmm0&lt;/font&gt;. Ostatnia instrukcja zapisuje wynik w &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;this&lt;/font&gt;. &lt;/font&gt;&lt;/font&gt;

&lt;p&gt;&lt;font face=&quot;Verdana&quot; color=&quot;#000000&quot;&gt;Na koniec omówimy sobie operator&lt;/font&gt; &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;new&lt;/font&gt; i &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;delete&lt;font face=&quot;Verdana&quot; color=&quot;#000000&quot;&gt;, ponieważ jak się okazuje, domyślne operatory nie będą kompatybilne z naszą klasą wektora. 
      &lt;br /&gt;W podstawowym ujęciu, instrukcje SSE dzielimy na dwie kategorie: operujące na wyrównanych i niewyrównanych danych. Gdy operujemy na danych niewyrównanych, działanie SSE jest nieco wolniejsze, ponieważ potrzeba więcej cykli by dostać się do odpowiedniej komórki pamięci. Przykładem tego typu instrukcji może być &lt;font face=&quot;Courier New&quot;&gt;mov&lt;strong&gt;u&lt;/strong&gt;ps&lt;/font&gt; – jest to odpowiednik &lt;font face=&quot;Courier New&quot;&gt;mov&lt;strong&gt;a&lt;/strong&gt;ps&lt;/font&gt; (&lt;strong&gt;u&lt;/strong&gt; – unaligned, &lt;strong&gt;a&lt;/strong&gt; - aligned), tylko, że tablica lub struktura, do której chcemy uzyskać dostęp, nie musi być wyrównana do granicy szesnastu bajtów. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color=&quot;#000000&quot;&gt;Cóż więc wspólnego mają z tym operatory &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;new&lt;/font&gt; i &lt;font face=&quot;Courier New&quot; color=&quot;#800000&quot;&gt;delete&lt;/font&gt;? To, że przydzielają one niewyrównane do odpowiadającej nam wartości, kawałki pamięci. Należy zatem operatory te przeciążyć. Na szczęście jest to operacja równie trywialna, jak te, które zaprezentowałem powyżej. Jeden ze sposobów zrobienia tego, &lt;a href=&quot;http://netrix.gamedev.pl/index.php/2008/12/08/wyrownanie-pamieci-dla-operatorow-new-i-new/&quot;&gt;opisał Netrix&lt;/a&gt;, mi jednak udało się, znaleźć znacznie prostsze rozwiązanie. Okazuje się bowiem, że istnieją funkcje które robią to za nas: &lt;font face=&quot;Courier New&quot;&gt;_aligned_malloc&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;_aligned_free&lt;/font&gt;. Zewnętrznie działają tak samo jak standardowe wersje &lt;font face=&quot;Courier New&quot;&gt;malloc&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;free&lt;/font&gt;, więc ich użytkowanie nie powinno sprawiać większego problemu. &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color=&quot;#000000&quot;&gt;Implementację dodawania i odejmowania zostawiam jako zadanie domowe :). Instrukcje, które je wykonują omówiłem w poprzedniej części kursiku więc nie powinno to stanowić większego problemu. &lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color=&quot;#000000&quot;&gt;W &lt;a href=&quot;http://odsiebie.com/pokaz/4735214---b340.html&quot;&gt;załączniku&lt;/a&gt; znajduje się kod do dzisiejszego kursiku. Dodałem także metodę zerującą wektor. &lt;/font&gt;&lt;/p&gt;</description><link>http://msemegen.blogspot.com/2009/08/sse-w-klasie-2_11.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>8</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-28637309827870099</guid><pubDate>Sat, 23 May 2009 14:55:00 +0000</pubDate><atom:updated>2009-05-23T16:55:46.059+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">krótka recenzja</category><title>Samsung yp-u1</title><description>&lt;p&gt;Dziś będzie trochę inna notka, nie nawiązująca zbyt wiele do programowania. Jak widać, znajduje się w kategorii krótka recenzja, lecz nie będę tu opisywał kolejnej, niezwykle fascynującej książki, z wciągającą fabułą i akcją. Chciałbym opisać niewielkie urządzenie, z którym miałem przyjemność spędzić ostatnie 3 lata. Nie jest to już więc sprzęt najnowszy, raczej ciężko go dziś kupić, jednak po tylu latach użytkowania chciałbym napisać kilka spostrzeżeń na temat tego niewielkiego odtwarzacza mp3.&lt;/p&gt;  &lt;p&gt;Na początek kilka podstawowych danych technicznych:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;wymiary&lt;/strong&gt;: 25.6 x 87.4 x 13.6 mm &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;waga&lt;/strong&gt;: 33g &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;zakres częstotliwości&lt;/strong&gt;: 20Hz~20KHz &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;czas odtwarzania&lt;/strong&gt;: 13h (wbudowany akumulator litowo-polimerowy) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Jak więc widać, jest to dość zgrabne i lekkie urządzenie. Dodatkowo bez problemów radzi sobie z formatami mp3 (także ze zmiennym bitrate) ogg, wma czy wav. Raz tylko zdarzył mi się plik, który podczas odtwarzania zawiesił odtwarzacz. Komunikacja z komputerem została rozwiązana standardowo: port USB 2.0, choć sposób chowania konektora jest nieco oryginalny (o tym później). Wyświetlacz jest cztero linijkowy, podświetlany w razie potrzeby na biało. Prezentowany tekst jest wyraźny i ostry. Nawet podczas przesuwania nie miga ani nie smuży, co często się zdarza w odtwarzaczach tego typu. Podświetlenie także nie pozostawia nic do życzenia – równomiernie rozłożone na całość ekranu. &lt;/p&gt;  &lt;p&gt;Posiadana przeze mnie wersja miała 512MB (YP-U1X), lecz dostępna ilość miejsca do za&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRbEHUPMHHVvvptP2tCziaR0oDcCYWRsM2A9Uja2bV1fkx59v_4S0Om91yBX-wgaRHUpGco_cfrnGNuBgDrjs0lmjSIuuXth242hibCfj113J8qv1tc6Kfo_a4wRn2U2hyphenhyphenvRhpk7oD0p0A/s1600-h/yp-u1_blg%5B21%5D.jpg&quot;&gt;&lt;img title=&quot;yp-u1_blg&quot; style=&quot;border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; margin-left: 0px; margin-right: 0px; border-right-width: 0px&quot; height=&quot;418&quot; alt=&quot;yp-u1_blg&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi226cguLK6a-6X8znUJJyB489jUDGEMAyp9mdQNg7XHHv2tWBFnENTUD0kZjzM8982fGmHMdsmzS3KbUI2AccSh_nnvITF9NiC5GoxuzAeReTnA-lLWoXQwARrQmC_IRHTtgsm1Aap-SUr/?imgmax=800&quot; width=&quot;328&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;pisu to 496MB.     &lt;br /&gt;Nawigacja po menu zostało zrobiona w sposób bardzo intuicyjny, szczególnie, że całość została przetłumaczona na język polski. Co ciekawe, “nieprzetłumaczalne” jest tylko “Settings” i “Language”, by po zmianie języka na koreański, bez problemów można było przywrócić stare ustawienia.     &lt;br /&gt;Główny ekran odtwarzania jest mocno konfigurowalny. Bez problemów można wyświetlić informacje na temat trybu odtwarzania, włączonego efektu dźwiękowego, bitrate (pliki ze zmiennym są oznaczane jako VBR), numeru pliku i poziomu baterii. Ciekawą opcją są dwa sposoby przewijania nazw utworów: poziomy i pionowy. Ten ostatni jest szczególnie przydatny, gdy nazwa piosenki jest dość długa by w krótkim czasie mogła zostać zaprezentowana w całości.     &lt;br /&gt;Nawigacja po drzewie plików też nie przysporzyła mi nigdy problemów – całość rozwiązana standardowo i intuicyjnie. Niektórym osobom nie podobał się sposób włączania&amp;#160; i wyłączania odtwarzacza: kilku sekundowe przytrzymanie przycisku Play. Przyznam, że nigdy nie miałem problemów z przypadkowym wyłączeniem playera, tym bardziej, że czas reakcji jest dość szybki, a dodatkowo jest możliwość włączenia “brzęczyka” – dźwiękowe informowanie o wciśniętych przyciskach. Odtwarzacz obsługuje także własny typ playlist. Nie korzystałem z nich jednak nigdy; wolałem standardową, “folderową” kolejność utworów.     &lt;br /&gt;Dodatkową opcją jest nagrywanie dźwięku, lecz należy traktować to jako dodatek. Jakość nagrań jest&amp;#160; bardzo zła, poza tym, zapisywane sa tylko w formacie wav.&lt;/p&gt;  &lt;p&gt;Zewnętrznie urządzenie zostało wykonane dość estetycznie. Warto zauważyć, że, wbrew pozorom, jest to bardzo mocna konstrukcja. Nie raz zdarzyło mi się, że podczas wyciągania telefonu z kieszeni, wypadł mi także player – działa do dziś.&lt;/p&gt;  &lt;p&gt;Wyżej wspominałem o ciekawym rozwiązaniu dotyczącym chowania wtyczki USB. Pierwszy raz spotkałem się z takim podejściem do problemu, by zamiast wysuwania, zastosować składanie – jest to ostatni (jeśli nie jedyny) model odtwarzacza mp3 Samsunga, który stosuje taki sposób. Niestety, po 3 latach intensywnego użytkowania (także często jako przenośna pamięć) rozwiązanie takie nie sprawdziło się. Jeśli przez pierwszy okres używania Yeepa nie było żadnych problemów, to teraz (zauważyłem to kilka miesięcy temu) urządzenie nie łączy się z komputerem w kilku warunkach. Przede wszystkim wejście USB nie może być zamontowane poziomo. Wówczas odtwarzacz opada (konektor się składa) i traci kontakt z komputerem – widać jakieś ruchome części odpowiedzialne za łączenie zostały uszkodzone.&amp;#160; &lt;br /&gt;Warto także zaznaczyć, że nie należy doprowadzać do zerowego stanu baterii. Często jest tak, że mimo informacji o niskim stanie akumulatora, po kilku chwilach odtwarzacz może zagrać jeszcze jeden, czy dwa utwory. Jest to jednak nie zalecane postępowanie. Ogólnie bateria sprawuje się dość dobrze – aktualnie trzyma od 6 do 8 godzin ciągłego odtwarzania muzyki. Warto zaznaczyć, że podświetlanie jest dość mocno “proądożerne” :)&lt;/p&gt;  &lt;p&gt;Dołączone w zestawie słuchawki są wykonane solidnie i charakteryzują się dobrą jakością dźwięku podobnie jak sam odtwarzacz – nie jestem jednak znawcą i audiofilem, więc opinie będą na ten temat różne.&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;Podsumowując: YP-U1 to solidnie, proste w obsłudze, dobrze wykonane urządzenie nie pozbawione jednak kilku wad. Bez problemu zmieści sie w kieszeni i pozwoli posłuchać ulubionej muzyki w prawie każdych warunkach. &lt;/p&gt;  </description><link>http://msemegen.blogspot.com/2009/05/samsung-yp-u1.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi226cguLK6a-6X8znUJJyB489jUDGEMAyp9mdQNg7XHHv2tWBFnENTUD0kZjzM8982fGmHMdsmzS3KbUI2AccSh_nnvITF9NiC5GoxuzAeReTnA-lLWoXQwARrQmC_IRHTtgsm1Aap-SUr/s72-c?imgmax=800" height="72" width="72"/><thr:total>11</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-8771671177130340940</guid><pubDate>Wed, 20 May 2009 07:57:00 +0000</pubDate><atom:updated>2009-08-06T09:18:19.160+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">assembler</category><category domain="http://www.blogger.com/atom/ns#">c++</category><title>SSE w praktyce - #1</title><description>&lt;p&gt;Dziś postaram się przedstawić podstawowe operacje jakie możemy wykonać przy użyciu multimedialnych rozszerzeń procesora. Pokażę możliwość bezpośredniego wykorzystania assemblera, zaś w następnych notkach skupię się na wewnętrznych poleceniach kompilatora, specjalnie przygotowanych do obsługi SSE. Aby prezentowany kod mógł zostać uruchomiony potrzebny jest procesor klasy Intel Pentium III lub lepszy.    &lt;br /&gt;Więc do dzieła ;)&lt;/p&gt;  &lt;p&gt;Jednak, jak to zwykle bywa, na początek jeszcze trochę teorii.    &lt;br /&gt;Programując przy użyciu SSE mamy do dyspozycji 8 dodatkowych, 128 bitowych rejestrów (w przypadku kodu dla procesorów 64 bitowych, liczba ta zwiększa sie do 16) - od xmm0 do xmm7. Wszystkie operacje, jakie będziemy chcieli wykonać przy użyciu omawianych tu instrukcji multimedialnych, będą operować właśnie na tych rejestrach. Jak już wiadomo, każdy z nich może przechować 4 wartości zmiennoprzecinkowe pojedynczej precyzji (&lt;span style=&quot;color: maroon&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;float&lt;/font&gt;&lt;/span&gt;). &lt;/p&gt;  &lt;p&gt;Na początek przygotujmy dane na których będziemy pracować: czteroelementowa, jednowymiarowa, wyrównana do 128 bitów tablica typu &lt;span style=&quot;color: maroon&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;float &lt;/font&gt;&lt;/span&gt;– czyli nasz wektor. &lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;__declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;)) &lt;span style=&quot;color: maroon&quot;&gt;float &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;gVector4&lt;/span&gt;[&lt;span style=&quot;color: blue&quot;&gt;4&lt;/span&gt;];&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Zobaczmy na początek, w jaki sposób możemy dostać się do danych naszego wektora. Nie będziemy tego robić standardowo,&lt;br /&gt;za pomocą operatora [ ] – posłużymy się do tego odpowiednimi instrukcjami SSE.&lt;br /&gt;Pierwszą podstawową rzeczą, będzie skopiowanie zawartości komórki pamięci, gdzie znajduje się nasz wektor, do rejestru xmm.&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    &lt;span style=&quot;color: #010001&quot;&gt;lea esi&lt;/span&gt;,&lt;span style=&quot;color: #010001&quot;&gt;gVector4
    movaps xmm0&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;]
    &lt;span style=&quot;color: gray&quot;&gt;//wykonaj operacje...
    &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;movaps &lt;/span&gt;[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;],&lt;span style=&quot;color: #010001&quot;&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Pierwsza linijka odpowiada za pobranie adresu zmiennej gVector4 (dokładny opis działania instrukcji &lt;font face=&quot;Courier New&quot;&gt;lea &lt;/font&gt;&lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;można znaleźć &lt;a href=&quot;http://rudy.mif.pg.gda.pl/~bogdro/dos/a_kurs03.htm&quot;&gt;tu&lt;/a&gt;)&lt;br /&gt;i skopiowanie go do rejestru &lt;font face=&quot;Courier New&quot;&gt;esi&lt;/font&gt; (wskaźnik danych). &lt;br /&gt;Następnie możemy zobaczyć już instrukcję z rodziny SSE – &lt;/font&gt;&lt;font face=&quot;Courier New&quot;&gt;movaps&lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;. Odpowiada ona za kopiowanie zawartości rejestrów xmm&lt;br /&gt;między sobą, a także pamięcią. W tym przypadku, zawartość komórki pamięci na który wskazuje rejestr &lt;font face=&quot;Courier New&quot;&gt;esi&lt;/font&gt;, zostanie przesłana do rejestru &lt;font face=&quot;Courier New&quot;&gt;xmm0&lt;/font&gt;. &lt;br /&gt;Ostatnia instrukcja kopiuje zawartość rejestru &lt;font face=&quot;Courier New&quot;&gt;xmm0&lt;/font&gt; pod adres wskazywany przez &lt;font face=&quot;Courier New&quot;&gt;esi&lt;/font&gt; – czyli do naszej zmiennej.&lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;Jak widać, mimo że jest to assembler, nie jest to takie trudne. &lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;Wygenerujmy więc nieco więcej bardziej praktycznego kodu. &lt;br /&gt;Jak pewnie zważyliście, deklarowanie za każdym razem owej specyficznej tablicy z pewnością nie należy do specjalnie wygodnych.&lt;br /&gt;Uprośćmy więc nieco ten proces:&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;typedef __declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;)) &lt;span style=&quot;color: maroon&quot;&gt;float &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;AlignedVector4D&lt;/span&gt;[&lt;span style=&quot;color: blue&quot;&gt;4&lt;/span&gt;];&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;font face=&quot;Verdana&quot;&gt;Ten niewielki kawałek kodu, z pewnością pozytywnie wpłynie na czytelność kodu.&lt;br /&gt;Poznajmy więc kilka podstawowych operacji: dodawanie, odejmowanie, mnożenie i dzielenie.&lt;br /&gt;Na początek zdefiniujmy dwa wektory, na których będziemy wykonywać nasze operacje:&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: #010001&quot;&gt;AlignedVector4D vec1 &lt;/span&gt;= {&lt;span style=&quot;color: blue&quot;&gt;5.0&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;6.0&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;3.0&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;1.0&lt;/span&gt;};
&lt;span style=&quot;color: #010001&quot;&gt;AlignedVector4D vec2 &lt;/span&gt;= {&lt;span style=&quot;color: blue&quot;&gt;2.5&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;3.0&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;1.5&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;0.5&lt;/span&gt;};&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;Za dodawanie odpowiada instrukcja &lt;font face=&quot;Courier New&quot;&gt;addps&lt;/font&gt;. Przykład użycia:&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    &lt;span style=&quot;color: #010001&quot;&gt;lea esi&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;vec1&lt;/span&gt;];
    &lt;span style=&quot;color: #010001&quot;&gt;lea edi&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;vec2&lt;/span&gt;];

    &lt;span style=&quot;color: #010001&quot;&gt;movaps xmm0&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;];
    &lt;span style=&quot;color: #010001&quot;&gt;movaps xmm1&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;edi&lt;/span&gt;];

    &lt;span style=&quot;color: #010001&quot;&gt;addps xmm0&lt;/span&gt;,&lt;span style=&quot;color: #010001&quot;&gt;xmm1&lt;/span&gt;;

    &lt;span style=&quot;color: #010001&quot;&gt;movaps &lt;/span&gt;[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;],&lt;span style=&quot;color: #010001&quot;&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Jak widać kod jest bardzo prosty. Dwie początkowe instrukcje odpowiadają za pobranie adresu zmiennych, następnie kopiujemy je&lt;br /&gt;do rejestrów xmm0 oraz xmm1 by dodać je do siebie w następnej instrukcji. Wynik zapisywany jest do xmm0 które jest kopiowane&lt;br /&gt;pod adres jaki wskazuje esi, czyli do zmiennej vec1. &lt;br /&gt;Zauważmy, że obecność kopiowania do rejestru xmm1 nie jest konieczna – addps, podobnie jak movaps może pracować na jednym&lt;br /&gt;operandzie znajdującym sie w pamięci operacyjnej:&lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    &lt;span style=&quot;color: #010001&quot;&gt;lea esi&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;vec1&lt;/span&gt;];
    &lt;span style=&quot;color: #010001&quot;&gt;lea edi&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;vec2&lt;/span&gt;];

    &lt;span style=&quot;color: #010001&quot;&gt;movaps xmm0&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;];
    &lt;span style=&quot;color: #010001&quot;&gt;addps xmm0&lt;/span&gt;,[&lt;span style=&quot;color: #010001&quot;&gt;edi&lt;/span&gt;];
    &lt;span style=&quot;color: #010001&quot;&gt;movaps &lt;/span&gt;[&lt;span style=&quot;color: #010001&quot;&gt;esi&lt;/span&gt;],&lt;span style=&quot;color: #010001&quot;&gt;xmm0
&lt;/span&gt;}&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Pozostałe operacje wykonuje się analogicznie:&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;subps&lt;/font&gt; – odejmowanie&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;mulps&lt;/font&gt; – mnożenie&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;divps&lt;/font&gt; – dzielenie&lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;To byłoby na tyle. W kolejnych częściach poznamy trochę więcej interesujących rzeczy ;)&lt;/font&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;</description><link>http://msemegen.blogspot.com/2009/05/sse-w-praktyce-1.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-6186324813234903496</guid><pubDate>Thu, 23 Apr 2009 00:52:00 +0000</pubDate><atom:updated>2009-04-23T02:52:45.602+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>Polimorfizm statyczny</title><description>&lt;p&gt;Główna metodą, dzięki której możemy zastosować polimorfizm to dziedziczenie, wraz z funkcjami (czysto) wirtualnymi. Jest to najbardziej intuicyjny sposób znany większości programistów. O tym, jak wygląda to od strony kompilatora, napisał swego czasu &lt;a href=&quot;http://xion.org.pl/&quot; target=&quot;_blank&quot;&gt;Xion&lt;/a&gt; w jednej ze swoich &lt;a href=&quot;http://xion.org.pl/2008/07/24/jak-dzialaja-metody-wirtualne/#comments&quot; target=&quot;_blank&quot;&gt;notek&lt;/a&gt;. Dziś jednak chciałbym się skupić na innej, rzadziej stosowanej, implementacji owej techniki.&lt;/p&gt;  &lt;p&gt;Główną wadą polimorfizmu jest jego wydajność. Dziś, w czasach rozkwitu języków zarządzanych, nie jest to problem wyjątkowo dotkliwy, jednak w pewnych zastosowaniach, nawet tak niewielkie narzuty muszą być brane pod uwagę. Mowa tu oczywiście o dynamicznym wiązaniu metod, których klasa zostaje ustalona dopiero podczas wykonywania programu. Jak można obejść ten problem? Stosując szablony. &lt;/p&gt;  &lt;p&gt;Przeanalizujmy prosty przykład: rysowanie i zarządzanie obiektami geometrycznymi.    &lt;br /&gt;Załóżmy, że chcemy przygotować klasę, która rysowałaby różnego rodzaju obiekty geometryczne: od punktów po wielokąty zdefiniowane przez użytkownika. Logicznym rozwiązaniem problemu, jest zastosowanie polimorfizmu. &lt;/p&gt;  &lt;p&gt;Na początek, stwórzmy więc interfejs definiujący operacje jakie ma wykonywać owy obiekt:&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;IGeometryObject&lt;/span&gt;{

    &lt;span style=&quot;color: maroon&quot;&gt;public&lt;/span&gt;:
        &lt;span style=&quot;color: maroon&quot;&gt;virtual void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;draw&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;void&lt;/span&gt;) = &lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;; &lt;span style=&quot;color: gray&quot;&gt;//rysowanie obiektu na plotnie
        &lt;/span&gt;&lt;span style=&quot;color: maroon&quot;&gt;virtual void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;setColor&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;unsigned &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;uColorType&lt;/span&gt;); &lt;span style=&quot;color: gray&quot;&gt;//ustawia kolor obiektu

        &lt;/span&gt;&lt;span style=&quot;color: maroon&quot;&gt;virtual void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;create&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;void&lt;/span&gt;) = &lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;; &lt;span style=&quot;color: gray&quot;&gt;//przydzielenie pamieci dla obiektu
        &lt;/span&gt;&lt;span style=&quot;color: maroon&quot;&gt;virtual void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;release&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;void&lt;/span&gt;) = &lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;; &lt;span style=&quot;color: gray&quot;&gt;//zwolnienie zasobow obiektu
&lt;/span&gt;};&lt;/pre&gt;

&lt;p&gt;Jak widać, nie ma tu nic szczególnego – klika metod czysto wirtualnych. Stwórzmy teraz metody innej klasy, których zadaniem jest rysowanie takich obiektów:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;CGeometryDrawer&lt;/span&gt;{

    &lt;span style=&quot;color: maroon&quot;&gt;public&lt;/span&gt;:

        &lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;drawObjectsList&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;std&lt;/span&gt;::&lt;span style=&quot;color: #010001&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #010001&quot;&gt;IGeometryObject&lt;/span&gt;*&amp;gt; &amp;amp;&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;){
            &lt;span style=&quot;color: maroon&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;unsigned &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;=&lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;.&lt;span style=&quot;color: #010001&quot;&gt;size&lt;/span&gt;();&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;++)&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;[&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;]-&amp;gt;&lt;span style=&quot;color: #010001&quot;&gt;draw&lt;/span&gt;();
        }

        &lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;drawObject&lt;/span&gt;(&lt;span style=&quot;color: #010001&quot;&gt;IGeometryObject &lt;/span&gt;*&lt;span style=&quot;color: #010001&quot;&gt;pObject&lt;/span&gt;){&lt;span style=&quot;color: #010001&quot;&gt;pObject&lt;/span&gt;-&amp;gt;&lt;span style=&quot;color: #010001&quot;&gt;draw&lt;/span&gt;();}
};&lt;/pre&gt;

&lt;p&gt;Główną zaletą takiego podejścia jest to, że kolekcja &lt;font face=&quot;Courier&quot;&gt;vElems &lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;może być heterogeniczna, czyli zawierać elementy różnych klas. Wystarczy tylko, że każda z nich będzie implementować interfejs &lt;/font&gt;&lt;font face=&quot;Courier&quot;&gt;&lt;span style=&quot;color: #010001&quot;&gt;IGeometryObject&lt;font face=&quot;Verdana&quot;&gt;. &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: #010001&quot;&gt;Był to więc przykład standardowego podejścia do problemu. Jak już wcześniej wspominałem, dla każdego wywołania jednej z wirtualnych metod interfejsu &lt;span style=&quot;color: #010001&quot;&gt;IGeometryObject&lt;/span&gt; musimy się liczyć z niewielkim narzutem, związanym z dynamicznym powiązaniem metody.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Czas na prezentację tytułowego sposobu. Podstawową różnicą będzie tu brak klasy, po której będzie obowiązek dziedziczenia – dzięki szablonom narzucimy odpowiedni interfejs wewnątrz metod:&lt;/span&gt;&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;class &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;CGeometryDrawer&lt;/span&gt;{

    &lt;span style=&quot;color: maroon&quot;&gt;public&lt;/span&gt;:

        &lt;span style=&quot;color: maroon&quot;&gt;template &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: maroon&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;GeometryObject&lt;/span&gt;&amp;gt;
        &lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;drawObjectsList&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;std&lt;/span&gt;::&lt;span style=&quot;color: #010001&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #010001&quot;&gt;GeometryObject&lt;/span&gt;&amp;gt; &amp;amp;&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;){
            &lt;span style=&quot;color: maroon&quot;&gt;for&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;unsigned &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;=&lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;.&lt;span style=&quot;color: #010001&quot;&gt;size&lt;/span&gt;();&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;++)&lt;span style=&quot;color: #010001&quot;&gt;vElems&lt;/span&gt;[&lt;span style=&quot;color: #010001&quot;&gt;i&lt;/span&gt;].&lt;span style=&quot;color: #010001&quot;&gt;draw&lt;/span&gt;();
        }

        &lt;span style=&quot;color: maroon&quot;&gt;template &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: maroon&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;GeometryObject&lt;/span&gt;&amp;gt;
        &lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;drawObject&lt;/span&gt;(&lt;span style=&quot;color: #010001&quot;&gt;GeometryObject &lt;/span&gt;&amp;amp;&lt;span style=&quot;color: #010001&quot;&gt;object&lt;/span&gt;){&lt;span style=&quot;color: #010001&quot;&gt;object&lt;/span&gt;.&lt;span style=&quot;color: #010001&quot;&gt;draw&lt;/span&gt;();}
};&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;p&gt;Jak widać, nowa wersja klasy rysującej korzysta z metod szablonowych. Metody te, definiując typ &lt;span style=&quot;color: #010001&quot;&gt;&lt;font face=&quot;Courier&quot;&gt;GeometryObject&lt;/font&gt;&lt;/span&gt;, narzucają dla niego obecność funkcji składowej &lt;font face=&quot;Courier&quot;&gt;draw&lt;/font&gt;. Dzięki temu, możemy przekazać obiekty dowolnych klas – istotne jest tylko to, by miały definicje &lt;font face=&quot;Courier&quot;&gt;draw&lt;/font&gt;. Ważne, by to metody były szablonowe, nie zaś cała klasa. W przeciwnym wypadku bylibyśmy ograniczeni tylko do obsługi typu przekazanego podczas definiowania obiektu klasy &lt;span style=&quot;color: #010001&quot;&gt;&lt;font face=&quot;Courier&quot;&gt;CGeometryDrawer&lt;/font&gt;&lt;/span&gt;. 

  &lt;br /&gt;Warto także zaznaczyć, że kolekcja &lt;font face=&quot;Courier&quot;&gt;vElems&lt;/font&gt; musi zawierać obiekty tego samego typu (homogeniczne). W przypadku polimorfizmu dynamicznego, dzięki zastosowaniu dziedziczenia, mogliśmy dodać do kolekcji, klasy różnych typów, w tym przypadku nie jest to jednak możliwe. Można co prawda, przekazać do metody &lt;span style=&quot;color: #010001&quot;&gt;&lt;font face=&quot;Courier&quot;&gt;drawObjectsList&lt;/font&gt;&lt;/span&gt; wektor wskaźników, ale wtedy funkcje składowe byłby wiązane dynamicznie, więc tracimy zyski związane ze statycznym wiązaniem. &lt;/p&gt;

&lt;p&gt;Ogólnie rzecz ujmując&lt;strong&gt; polimorfizm dynamiczny&lt;/strong&gt; można określić jako: &lt;em&gt;powiązany&lt;/em&gt; i &lt;em&gt;dynamiczny&lt;/em&gt;. &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;powiązany&lt;/em&gt;, ponieważ typy obiektów są zależne od innego typu (dziedziczenie po klasie bazowej, w tym przypadku interfejsie) &lt;/li&gt;

  &lt;li&gt;&lt;em&gt;dynamiczny&lt;/em&gt;, bo klasa wywoływanej metody jest ustalana podczas działania programu. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do jego podstawowych zalet można zaliczyć:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;możliwość działania na kolekcjach heterogenicznych obiektów&lt;/li&gt;

  &lt;li&gt;metody korzystające z polimorfizmu mogą być dostarczane w postaci skompilowanej (lib lub dll)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Polimorfizm statyczny&lt;/strong&gt; jest zaś &lt;em&gt;niepowiązany&lt;/em&gt; i &lt;em&gt;statyczny&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;niepowiązany&lt;/em&gt;, bo klasy konkretne (niewirtualne) nie muszą być dziedziczone po określonym interfejsie lub innej klasie&lt;/li&gt;

  &lt;li&gt;&lt;em&gt;statyczny&lt;/em&gt; – klasy metod są ustalane już na etapie kompilacji&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zalety:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;większa wydajność&lt;/li&gt;

  &lt;li&gt;klasy konkretne nie muszą implementować całości określonego interfejsu, ponieważ wymagana jest znajomość tylko tych operacji które są rzeczywiście wywoływane w programie&lt;/li&gt;

  &lt;li&gt;istnieje możliwość stosowania typów podstawowych&lt;/li&gt;
&lt;/ul&gt;  </description><link>http://msemegen.blogspot.com/2009/04/polimorfizm-statyczny.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-2117488252319635723</guid><pubDate>Fri, 13 Mar 2009 01:42:00 +0000</pubDate><atom:updated>2009-03-13T03:05:30.810+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">assembler</category><category domain="http://www.blogger.com/atom/ns#">c++</category><title>CPUID, czyli procesorze przedstaw się</title><description>&lt;p&gt;We wcześniejszych notkach pisałem o technologii SSE. &lt;a href=&quot;http://bsmechanik.blogspot.com/2008/12/wicej-mocy.html&quot;&gt;Krótki opis&lt;/a&gt;, &lt;a href=&quot;http://bsmechanik.blogspot.com/2009/01/kompilator-vs-inline-asembler_06.html&quot;&gt;wsparcie ze strony kompilatora&lt;/a&gt; – czas więc na bardziej praktyczne podejście do tematu. W artykule tym skupię się jednak na działaniu instrukcji, która nie jest związana bezpośrednio z technologią SSE, a mianowicie na CPUID - proste, bezargumentowe polecenie, pozwalające uzyskać wiele przydatnych informacji na temat procesora. &lt;/p&gt;  &lt;p&gt;Pisząc program korzystający z zestawu instrukcji SIMD, chcemy czasem zachować zgodność ze starszymi modelami procesorów, które nie wspomagają konkretnej wersji SSE lub 3DNow!. Wykorzystując także najnowsze wersje rozszerzeń multimedialnych (aktualnie jest to 4.1), musimy mieć na uwadze to, że wielu użytkowników nie posiada jeszcze procesorów, które je potrafią obsłużyć. Aby nie ograniczać liczby potencjalnych odbiorców, musimy więc zaopatrzyć się w metody, które wykonają stosowne obliczenia w sposób tradycyjny, lub za pomocą niższych wersji SSE. Problemem pozostaje oczywiście pobranie informacji o tym, jaki typ funkcji możemy wykonać na procesorze użytkownika. Rozwiązanie jest wbrew pozorom dość proste. Przyjrzyjmy się kilku z nich. &lt;/p&gt;  &lt;p&gt;Jeśli interesuje nas lista podstawowych możliwości, możemy skorzystać z funkcji udostępnianych przez Windows Api: &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms724482(VS.85).aspx&quot; target=&quot;_blank&quot;&gt;IsProcessorFeaturePresent&lt;/a&gt; i &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms724381(VS.85).aspx&quot; target=&quot;_blank&quot;&gt;GetSystemInfo&lt;/a&gt;. Pierwsza z nich zwraca informacje o wersji obsługiwanych SSE (niestety, tylko do wersji trzeciej), MMX, 3DNow! a także garść innych danych (choćby dostępność &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa366796(VS.85).aspx&quot; target=&quot;_blank&quot;&gt;Physical Address Extension&lt;/a&gt;). Kolejna z wymienionych funkcji, może być szczególnie przydatna, bo za jej pomocą można dowiedzieć się, ile fizycznych procesorów jest aktualnie zainstalowanych w systemie. Pobiera także dane dotyczące m.in. rozmiaru strony w pamięci operacyjnej.     &lt;br /&gt;Skorzystanie z powyższej funkcjonalności jest bardzo proste, zaś przykłady są na stronach ich dokumentacji, więc nie będę prezentował ich użycia.&lt;/p&gt;  &lt;p&gt;Sprawdzanie jednak, czy procesor posiada obsługę MMX, w dzisiejszych czasach, nie jest już koniecznie wymagane – od ładnych kilku lat, należy to do standardowej funkcjonalności procesorów rodziny x86. Co jednak, gdy chcemy skorzystać z udogodnień SSE 4.1? Jego obsługa dziś nie jest jeszcze tak oczywista, podobnie jak SSSE 3. Tu z pomocą przychodzi nam assembler.    &lt;br /&gt;Instrukcja &lt;font face=&quot;Courier New&quot;&gt;CPUID&lt;/font&gt; dostępna jest od rodziny procesorów Pentium i późniejszych Intel486. Nie wszystkie funkcje były wspomagane od razu, jednak od czasów Pentium 4, sytuacja nie zmieniła się zbyt mocno.     &lt;br /&gt;Ogólna idea działania jest bardzo prosta: do rejestru &lt;font face=&quot;Courier New&quot;&gt;EAX &lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;przekazujemy numer funkcji (operacje jaką chcemy wykonać), wywołujemy instrukcję &lt;font face=&quot;Courier New&quot;&gt;CPUID&lt;/font&gt; i dostajemy interesujące nas informacje w odpowiednich rejestrach. Na początek pobierzmy nazwę producenta – jest to 12 znakowy łańcuch, zapisany w 3 rejestrach:&lt;/font&gt;&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt; &lt;span style=&quot;color: maroon&quot;&gt;char &lt;/span&gt;&lt;span style=&quot;color: #020002&quot;&gt;szName&lt;/span&gt;[&lt;span style=&quot;color: blue&quot;&gt;13&lt;/span&gt;];

&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    &lt;span style=&quot;color: #020002&quot;&gt;mov eax&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;0x00000000&lt;/span&gt;;
    &lt;span style=&quot;color: #020002&quot;&gt;cpuid&lt;/span&gt;;
 
    &lt;span style=&quot;color: #020002&quot;&gt;mov DWORD PTR szName&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;ebx 
    mov DWORD PTR szName&lt;/span&gt;+&lt;span style=&quot;color: blue&quot;&gt;4&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;edx 
    mov DWORD PTR szName&lt;/span&gt;+&lt;span style=&quot;color: blue&quot;&gt;8&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;ecx
&lt;/span&gt;}

&lt;span style=&quot;color: #020002&quot;&gt;szName&lt;/span&gt;[&lt;span style=&quot;color: blue&quot;&gt;12&lt;/span&gt;] = &lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;;
&lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;%s\n&amp;quot;&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;szName&lt;/span&gt;);&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;Na procesorach Intela zostanie wyświetlone: &lt;font face=&quot;Courier New&quot;&gt;GenuineIntel&lt;font face=&quot;Verdana&quot;&gt;, zaś AMD:&lt;/font&gt; &lt;/font&gt;&lt;/font&gt;AuthenticAMD.&lt;font face=&quot;Verdana&quot;&gt; &lt;br /&gt;Jak to działa? Bardzo prosto. &lt;br /&gt;Pierwsza instrukcja &lt;font face=&quot;Courier New&quot;&gt;mov&lt;/font&gt; zapisuje do rejestru &lt;font face=&quot;Courier New&quot;&gt;EAX&lt;/font&gt; numer funkcji (w tym przypadku jest to funkcja o numerze 0). Następnie wywołujemy &lt;font face=&quot;Courier New&quot;&gt;CPUID&lt;/font&gt;, które pobiera numer funkcji z rejestru &lt;font face=&quot;Courier New&quot;&gt;EAX&lt;/font&gt; i wykonuje odpowiednią operacje. Funkcja, którą przekazaliśmy, zwraca wspomniany już identyfikator producenta procesora, w porcjach czterobajtowych, w rejestrach &lt;font face=&quot;Courier New&quot;&gt;EBX&lt;/font&gt;, &lt;font face=&quot;Courier New&quot;&gt;EDX&lt;/font&gt;, &lt;font face=&quot;Courier New&quot;&gt;ECX&lt;/font&gt;. Aby dostać się do niego, przekazujemy do instrukcji &lt;font face=&quot;Courier New&quot;&gt;mov&lt;/font&gt; wskaźnik na tablicę &lt;font face=&quot;Courier New&quot;&gt;szName&lt;/font&gt; (warto przypomnieć, że nazwa tablicy jest jednocześnie wskaźnikiem jej początku) i nazwę konkretnego rejestru – ważne aby zastosować zaprezentowaną kolejność by dostać prawidłowo “poskładany” łańcuch. Pod przekazany adres tablicy kopiowana jest zawartość czterobajtowych rejestrów, więc, żeby uzupełnić tablicę, zwiększamy wskaźnik o ilość skopiowanych dotychczas danych (czyli właśnie 4 bajty) dla rejestrów &lt;font face=&quot;Courier New&quot;&gt;EDX&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;ECX&lt;/font&gt;.&lt;/font&gt;

&lt;font face=&quot;Verdana&quot;&gt;Nie było to więc zbyt trudne zadanie. Dowiedzmy się więc, coś na temat SSE. Numer funkcji, za pomocą której dowiemy się o wspieranych przez procesor wersjach SSE, to &lt;font face=&quot;Courier New&quot;&gt;0x0000001&lt;/font&gt;, zaś interesujące nas informacje (czyli Standard Feature Flags) będą się znajdować w rejestrach &lt;font face=&quot;Courier New&quot;&gt;EDX&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;ECX&lt;/font&gt;. &lt;/font&gt;

&lt;pre class=&quot;code&quot;&gt; &lt;span style=&quot;color: maroon&quot;&gt;unsigned &lt;/span&gt;&lt;span style=&quot;color: #020002&quot;&gt;s1&lt;/span&gt;, &lt;span style=&quot;color: #020002&quot;&gt;s2&lt;/span&gt;;

&lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
    &lt;span style=&quot;color: #020002&quot;&gt;mov eax&lt;/span&gt;,&lt;span style=&quot;color: blue&quot;&gt;0x00000001&lt;/span&gt;;
    &lt;span style=&quot;color: #020002&quot;&gt;cpuid&lt;/span&gt;;

    &lt;span style=&quot;color: #020002&quot;&gt;mov s1&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;edx&lt;/span&gt;;
    &lt;span style=&quot;color: #020002&quot;&gt;mov s2&lt;/span&gt;,&lt;span style=&quot;color: #020002&quot;&gt;ecx&lt;/span&gt;;
}&lt;/pre&gt;

&lt;p&gt;Zmienne &lt;font face=&quot;Courier New&quot;&gt;s1&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;s2&lt;/font&gt; zostały wykorzystane tu jako wektory bitowe – każdy z 32 bitów przechowuje wartość 0 lub 1 (właściwość jest lub nie jest dostępna). W rejestrze &lt;font face=&quot;Courier New&quot;&gt;EDX&lt;/font&gt; (więc u nas w zmiennej &lt;font face=&quot;Courier New&quot;&gt;s1&lt;/font&gt;) przechowywane są informacje na temat dostępności MMX (bit 23), SSE (bit 25), SSE2 (bit 26). Czy jest obsługiwane SSE w wersji trzeciej dowiemy się sprawdzając bit zerowy zmiennej &lt;font face=&quot;Courier New&quot;&gt;s2&lt;/font&gt;, SSSE3 bit 9 a SSE4.1 bit 19. Jak to zrobimy? Oczywiście posługując się operatorem &lt;font face=&quot;Courier New&quot;&gt;&amp;gt;&amp;gt;&lt;/font&gt; (jego działanie i typowe zastosowanie opisał &lt;a href=&quot;http://xion.org.pl/&quot; target=&quot;_blank&quot;&gt;Xion&lt;/a&gt;, w swoim &lt;a href=&quot;http://www.gamedev.pl/tutorials.php?x=view&amp;amp;id=217&quot; target=&quot;_blank&quot;&gt;megatutorialu&lt;/a&gt;). 

  &lt;br /&gt;Ogólny schemat wygląda następująco:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;((&lt;span style=&quot;color: #020002&quot;&gt;zmienna &lt;/span&gt;&amp;gt;&amp;gt; &lt;span style=&quot;color: #020002&quot;&gt;numer_bitu&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color: blue&quot;&gt;1&lt;/span&gt;) ? &lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;jest&amp;quot;&lt;/span&gt;) : &lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;nie ma&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;Czyli, jeśli chcemy sprawdzić dostępność SSE2, piszemy:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;((&lt;span style=&quot;color: #020002&quot;&gt;s1 &lt;/span&gt;&amp;gt;&amp;gt; &lt;span style=&quot;color: blue&quot;&gt;26&lt;/span&gt;) &amp;amp; &lt;span style=&quot;color: blue&quot;&gt;1 &lt;/span&gt;)? &lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;jest\n&amp;quot;&lt;/span&gt;) : &lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;nie ma\n&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;Dla bitu zerowego (SSE3), nie musimy wywoływać operatora &lt;font face=&quot;Courier New&quot;&gt;&amp;gt;&amp;gt;&lt;/font&gt;. &lt;/p&gt;

&lt;p&gt;Możemy także ubezpieczyć się, przed (czysto teoretyczną) sytuacją braku wsparcia dla CPUID. W takim przypadku, gdy spróbujemy wykonać tą instrukcję, wyrzucany jest wyjątek, zaś naszym zadaniem jest przechwycenie go. &lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;__try&lt;/span&gt;{

    &lt;span style=&quot;color: maroon&quot;&gt;_asm&lt;/span&gt;{
        &lt;span style=&quot;color: gray&quot;&gt;//...
        &lt;/span&gt;&lt;span style=&quot;color: #020002&quot;&gt;cpuid
        &lt;/span&gt;&lt;span style=&quot;color: gray&quot;&gt;//...
    &lt;/span&gt;}

}
&lt;span style=&quot;color: maroon&quot;&gt;__except&lt;/span&gt;(&lt;span style=&quot;color: #020002&quot;&gt;EXCEPTION_EXECUTE_HANDLER&lt;/span&gt;) { 
    &lt;span style=&quot;color: maroon&quot;&gt;if &lt;/span&gt;(&lt;span style=&quot;color: #020002&quot;&gt;_exception_code&lt;/span&gt;() == &lt;span style=&quot;color: #020002&quot;&gt;STATUS_ILLEGAL_INSTRUCTION&lt;/span&gt;){
        &lt;span style=&quot;color: #020002&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;Instrukcja nie jest wspierana przez procesor. &amp;quot;&lt;/span&gt;);
    }
}&lt;/pre&gt;

&lt;font face=&quot;Verdana&quot;&gt;W tym przypadku mamy możliwość złapania wyjątku systemowego, a taki zostanie wyrzucony, jeśli spróbujemy użyć instrukcji nie wspieranej przez nasz procesor. Tak samo można zrobić dla instrukcji SIMD, jednak moim zdaniem nie jest to eleganckie. W przypadku CPUID, taki kod “opakowujący” jest użyty na wszelki wypadek i jego wykonanie jest praktycznie znikome, zaś dla SSE szanse te znacznie rosną i powinniśmy wykryć odpowiednie właściwości znacznie wcześniej.  &lt;/font&gt;


&lt;p&gt;Dokładny opis CPUID znajdziemy oczywiście w podręcznikach Intela, szczególnie w &lt;em&gt;IA-32 Intel Architecture Software Developer’s Manual VOLUME 2A: Instruction Set Reference, A-M, &lt;/em&gt;stronach 3-179 do 3-208. Warto wspomnieć, że za pomocą tej instrukcji, możemy dowiedzieć się bardzo wielu niskopoziomowych szczegółów na temat procesora. &lt;/p&gt;</description><link>http://msemegen.blogspot.com/2009/03/cpuid-czyli-procesorze-przedstaw-sie.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-7189747207983898422</guid><pubDate>Wed, 25 Feb 2009 22:22:00 +0000</pubDate><atom:updated>2009-02-25T23:25:39.607+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Istotna kolejność</title><description>&lt;p&gt;Dzięki operatorowi &lt;font color=&quot;#333333&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;sizeof&lt;/span&gt;() &lt;/font&gt;&lt;font face=&quot;Verdana&quot;&gt;możemy dowiedzieć się jaki jest rozmiar danego typu w bajtach. Standard świadomie nie określa odgórnych rozmiarów typów podstawowych, zostawiając to zależnym od platformy sprzętowej (opisane są tylko relacje wielkości pomiędzy typami). Mimo, że wszystkie produkowane dziś procesory operują na słowach 64 bitowych, to jednak znaczna większość użytkowników posiada 32 bitowe systemy operacyjne, dla których tworzony jest kod aplikacji. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color=&quot;#333333&quot;&gt;&lt;font face=&quot;Verdana&quot;&gt;Przypatrzmy się więc dwóm z pozoru identycznym strukturom:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;A&lt;/span&gt;{
    &lt;span style=&quot;color: maroon&quot;&gt;short &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;a1&lt;/span&gt;;
    &lt;span style=&quot;color: maroon&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;b1&lt;/span&gt;;
    &lt;span style=&quot;color: maroon&quot;&gt;short &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;a2&lt;/span&gt;;
};
&lt;span style=&quot;color: maroon&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;B&lt;/span&gt;{
    &lt;span style=&quot;color: maroon&quot;&gt;short &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;a1
    &lt;/span&gt;&lt;span style=&quot;color: maroon&quot;&gt;short &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;a2&lt;/span&gt;;
    &lt;span style=&quot;color: maroon&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color: #010001&quot;&gt;b1&lt;/span&gt;;
};&lt;/pre&gt;&lt;p&gt;&lt;font color=&quot;#333333&quot;&gt;&lt;font face=&quot;Verdana&quot;&gt;Mają służyć tylko jako przykład, więc nie są to wyjątkowo praktyczne typy. Jak widzimy obydwie struktury mają po dwa pola typu &lt;span style=&quot;color: maroon&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;short&lt;/font&gt;&amp;#160;&lt;font color=&quot;#000000&quot;&gt;i jedno typu &lt;span style=&quot;color: maroon&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;int&lt;/font&gt;&lt;font color=&quot;#000000&quot;&gt;.&lt;/font&gt;&lt;/span&gt; Zróbmy teraz mały eksperyment i wyświetlmy rozmiary obu tych typów:&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: #010001&quot;&gt;printf&lt;/span&gt;(&lt;span style=&quot;color: red&quot;&gt;&amp;quot;%d %d\n&amp;quot;&lt;/span&gt;,&lt;span style=&quot;color: maroon&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #010001&quot;&gt;A&lt;/span&gt;), &lt;span style=&quot;color: maroon&quot;&gt;sizeof&lt;/span&gt;(&lt;span style=&quot;color: #010001&quot;&gt;B&lt;/span&gt;));&lt;/pre&gt;&lt;p&gt;Naszym oczom ukaże się dość zadziwiający widok, bo rozmiary typów &lt;font face=&quot;Courier New&quot;&gt;A&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;B&lt;/font&gt; są różne, i wynoszą odpowiednio 12 i 8 bajtów (na procesorze z rodziny IA-32). Dość zaskakujące, nieprawdaż? Tylko z pozoru. 
  &lt;br /&gt;Zacznijmy więc od początku. Z prostego dodawania wynika, że obie te struktury powinny zajmować 8 bajtów (2+2+4). Pierwsza z nich jednak, zajmuje o 4 bajty więcej. W tym momencie przyda się podstawowa wiedza na temat działania procesora. Danymi, na których procesory 32 bitowe, pracują z największą wydajnością to właśnie 32 bity. Tyle wynosi rozmiar słowa i rejestrów ogólnego przeznaczenia. Wysłanie większej, lub mniejszej, ilości danych, jest realizowane wolniej, dlatego nie zawsze zaleca się ich używanie. Spójrzmy teraz na strukturę &lt;font face=&quot;Courier New&quot;&gt;A&lt;/font&gt;. Aby efektywnie móc przesłać wartość jej pól do rejestrów, najlepiej zrobić to 32 bitowymi paczkami. Napotykamy jednak na problem. Wedle tej idei, zmienną &lt;font face=&quot;Courier New&quot;&gt;b1&lt;/font&gt; trzeba wysyłać 2 razy (po 16 bitów wraz z &lt;font face=&quot;Courier New&quot;&gt;a1&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;a2&lt;/font&gt;). Nie jest bezpieczne i poprawne rozwiązanie. W takim przypadku kompilatory stosują bardzo prostą sztuczkę: wyrównują zmienne do 32 bitów, co w tym przypadku oznacza, że &lt;font face=&quot;Courier New&quot;&gt;a1&lt;/font&gt; oraz &lt;font face=&quot;Courier New&quot;&gt;a2&lt;/font&gt; będą zajmować po 4 bajty. Na każdej z tych zmiennych zyskujemy dodatkowo po 2 bajty, więc zagadka została wyjaśniona. Dlaczego więc struktura &lt;font face=&quot;Courier New&quot;&gt;B&lt;/font&gt;, zajmuje 8 bajtów? Decyduje o tym właśnie ułożenie zmiennych. W tym przypadku zmienne &lt;font face=&quot;Courier New&quot;&gt;a1&lt;/font&gt; i &lt;font face=&quot;Courier New&quot;&gt;a2&lt;/font&gt; można wysłać za pomocą jednego wywołania instrukcji &lt;font face=&quot;Courier New&quot;&gt;mov&lt;/font&gt;, więc wyrównanie ich nie jest potrzebne. 
  &lt;br /&gt;Obrazowo można przedstawić to tak, że struktura (a zarazem i klasa) to pojemnik z 32 bitowymi (lub 64, w przypadku procesorów i systemów operacyjnych 64 bitowych) pudełkami, do których są kolejno dodawane zmienne. Jeśli dana zmienna nie zajmuje całego pudełka, a kolejna zmienna już nie mieści się do niego, wolne miejsce zostaje zapełnione – natura nie lubi próżni. :)&amp;#160; &lt;/p&gt;</description><link>http://msemegen.blogspot.com/2009/02/istotna-kolejnosc.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8323132172904612534.post-3061308374971830938</guid><pubDate>Mon, 05 Jan 2009 23:05:00 +0000</pubDate><atom:updated>2009-02-26T19:28:39.539+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">assembler</category><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><title>Kompilator vs. inline assembler</title><description>&lt;p&gt;
Optymalizacje niskopoziomowe, mimo że stosowane coraz rzadziej, nadal w wielu przypadkach, są jedynym wyjściem by przyśpieszyć działanie aplikacji. Z roku na rok jednak, kompilatory czynią dość znaczące postępy w automatycznym optymalizowaniu kodu i nie zawsze musimy uciekać się do drastycznych metod wstawek asemblerowych, które wbrew powszechnej opinii, nie są już zalecane. Przyjrzyjmy się jednak jednemu, specyficznemu przypadkowi: użycie SSE.&lt;br&gt;Mamy trzy możliwości do wyboru:
&lt;ol&gt;&lt;li&gt;Optymalizacje stosowane przez kompilator (w opisywanym przypadku Visual Studio 2008).&lt;/li&gt;&lt;li&gt;Użycie wewnętrznych poleceń, tzw. intrinsic. &lt;/li&gt;&lt;li&gt;Bezpośrednie zastosowanie instrukcji SSE procesora.&lt;/li&gt;&lt;/ol&gt;Będziemy wykonywać operacje na wektorach, które będą reprezentowane przez zwykłą, wyrównaną do 16 bajtów (128 bitów) tablicą 4 wartości float:&lt;p&gt;&lt;span style=&quot;color: maroon&quot;&gt;__declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;)) &lt;span style=&quot;color: maroon&quot;&gt;float &lt;/span&gt;vector[&lt;span style=&quot;color: blue&quot;&gt;4&lt;/span&gt;];&lt;/p&gt;Pewnie wiele osób zastanawia się, skąd ta dziwna składnia tworzenia tablicy. Wyrównanie danych narzuca restrykcje dotyczące rozmiaru. Wyrównanie do 16 bajtów (czyli polecenie &lt;span style=&quot;color: maroon&quot;&gt;__declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;) ) informuje nas, że określona zmienna będzie zajmować dokładnie tyle. Przypomnijmy, że rejestry SSE są 128 bitowe i aby optymalnie wykonywać operacje musimy wysyłać dane do nich właśnie takimi, 128 bitowymi, paczkami. 
Aby porównać ze sobą wymienione wyżej trzy sposoby optymalizacji, zajrzymy do kodu wynikowego generowanego przez kompilator. Można to zrobić wchodząc we właściwości projektu (Project-&gt;Properties), następnie w zakładkę C++, Output Files i tam ustawić Aseembler Output na Assembly With Source Code. Będziemy porównywać podstawowe operacje typu przy zastosowaniu pierwszej wersji SSE, wektorem zaś będzie struktura:&lt;p&gt;&lt;span style=&quot;color: maroon&quot;&gt;struct &lt;/span&gt;Vector{&lt;br/&gt;&lt;span style=&quot;color: maroon&quot;&gt;__declspec&lt;/span&gt;(&lt;span style=&quot;color: maroon&quot;&gt;align&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;16&lt;/span&gt;)) &lt;span style=&quot;color: maroon&quot;&gt;float &lt;/span&gt;data[&lt;span style=&quot;color: blue&quot;&gt;4&lt;/span&gt;];&lt;br /&gt;};&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. Optymalizacje kompilatora.&lt;/strong&gt;&lt;/p&gt;Jest to najprostszy sposób by użyć dodatkowej mocy procesora. Zaznaczamy kilka checkbox’ów, rekompilujemy projekt i dostajemy szybszy (przynajmniej w teorii) program. Zobaczmy jak sytuacja przedstawia się, gdy chcemy użyć SSE. 
Na początek przejdźmy do opcji projektu i tam C++ -&gt; Code Generation -&gt; Enable Enhanced Instruction Set ustawiamy na Streaming SIMD Extensions. Mając wszystko przygotowane, możemy przystąpić do pracy.&lt;p&gt;Posłużmy się prostą funkcją dodającą wektory:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;] = v1.data[&lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;] + v2.data[&lt;span style=&quot;color: blue&quot;&gt;0&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;1&lt;/span&gt;] = v1.data[&lt;span style=&quot;color: blue&quot;&gt;1&lt;/span&gt;] + v2.data[&lt;span style=&quot;color: blue&quot;&gt;1&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;2&lt;/span&gt;] = v1.data[&lt;span style=&quot;color: blue&quot;&gt;2&lt;/span&gt;] + v2.data[&lt;span style=&quot;color: blue&quot;&gt;2&lt;/span&gt;];&lt;br&gt;&amp;#9;pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;3&lt;/span&gt;] = &lt;span style=&quot;color: blue&quot;&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Warto zauważyć, że element w, czyli ostatni, powinien być ustawiany na wartość 1.0f. Nie zastosowałem tutaj pętli, choć kompilator przy tak niewielkiej ilości iteracji i tak zastosowałby rozwinięcie.&lt;/p&gt;&lt;p&gt;Spójrzmy teraz na kod, który został wyprodukowany:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: gray&quot;&gt;//; 8    :     pOut-&amp;gt;data[0] = v1.data[0] + v2.data[0];&lt;/span&gt;&lt;br&gt;    mov    eax, DWORD PTR _v1$[ebp]&lt;br&gt;    fld    DWORD PTR [eax]&lt;br&gt;    mov    ecx, DWORD PTR _v2$[ebp]&lt;br&gt;    fadd    DWORD PTR [ecx]&lt;br&gt;    mov    edx, DWORD PTR _pOut$[ebp]&lt;br&gt;    fstp    DWORD PTR [edx]&lt;br&gt;&lt;span style=&quot;color: gray&quot;&gt;//; 9    :     pOut-&amp;gt;data[1] = v1.data[1] + v2.data[1];&lt;br&gt;    //dodawanie wartosci y
//; 10   :     pOut-&amp;gt;data[2] = v1.data[2] + v2.data[2];&lt;br&gt;    //dodawanie wartosci z
//; 12   :     pOut-&amp;gt;data[3] = 1.0f;&lt;br&gt;&lt;/span&gt;    mov    eax, DWORD PTR _pOut$[ebp]&lt;br&gt;    movss    xmm0, DWORD PTR __real@&lt;span style=&quot;color: blue&quot;&gt;3f800000&lt;br&gt;&lt;/span&gt;    movss    DWORD PTR [eax+&lt;span style=&quot;color: blue&quot;&gt;12&lt;/span&gt;], xmm0&lt;/pre&gt;&lt;p&gt;Pominąłem tu prolog i epilog funkcji, bo nie są w tym momencie istotne. Nie ma także dodawania elementów y i z, ponieważ jest to realizowane w taki sam sposób jak dla elementu x. Zmieniane są tylko wartości rejestrów ecx dla instrukcji fadd (która odpowiada za dodawanie przez koprocesor FPU), oraz rejestru edx dla funkcji fstp odpowiednio o 4 (współrzędna x) i 8 (współrzędna y). Jak widać, samo dodawanie jest realizowane standardowo. Pierwszy raz instrukcja SSE jest użyta podczas przypisania elementu w (data[3]) – movss odpowiedzialna za ustawienie najniższej wartości rejestru na odpowiednią wartość.&lt;/p&gt;&lt;p&gt;Wnioski są bardzo proste: korzystanie z optymalizacji dostarczanych przez kompilator (w kontekście korzystania z SSE) nie dają zbyt wiele korzyści, a czasem nawet mogą zaszkodzić – powyższy kod nie uruchomi się na procesorach niższej klasy niż pentuim III – wszystko przez jedną instrukcję movss, która de facto, nie przyśpieszyła zauważalnie naszego kodu.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. Wewnętrzne polecenia kompilatora.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Są to instrukcje, dzięki którym kompilator wie jak poprawnie użyć poleceń asemblera. By móc z nich skorzystać musimy dołączyć do projektu nagłówek xmmintrin.h, gdzie znajdują się wszystkie deklaracje funkcji i typów. Także i w tym przypadku wykorzystamy prostą funkcję dodającą dwa wektory:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;     _mm_store_ps(pOut-&amp;gt;data,_mm_add_ps(*(&lt;span style=&quot;color: maroon&quot;&gt;__m128&lt;/span&gt;*)&amp;amp;v1.data,*(&lt;span style=&quot;color: maroon&quot;&gt;__m128&lt;/span&gt;*)&amp;amp;v2.data));&lt;br&gt;     pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;3&lt;/span&gt;] = &lt;span style=&quot;color: blue&quot;&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Tak. Oto cała funkcja. Dodaje ona dwa wektory, więc funkcjonalnością jest ona identyczna z tą zaprezentowaną wcześniej. Na tym jednak kończą się podobieństwa. Jak widać sposób dodawania jest tutaj inny. Jest on wykonywany za pomocą funkcji _mm_add_ps, przyjmującej zmienne typu __m128 – by przekazać wyrównaną tablicę trzeba użyć rzutowania. Za pomocą _mm_store_ps zapisujemy wartość typu __m128, zwracaną przez _mm_add_ps, do tablicy. Zostaje jeszcze przypisanie wartości dla w. Tworząc własną klasę do zarządzania wektorami, można pominąć tę operację, dodając metodę dostępową zwracającą dla w zawsze 1.0f – wartość zapisana w ostatniej komórce będzie więc bez znaczenia.&lt;/p&gt;&lt;p&gt;Zobaczmy więc, co zostało ostatecznie wygenerowane:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;    mov    eax, DWORD PTR _v2$[ebx]&lt;br&gt;    movaps    xmm0, XMMWORD PTR [eax]&lt;br&gt;    mov    ecx, DWORD PTR _v1$[ebx]&lt;br&gt;    movaps    xmm1, XMMWORD PTR [ecx]&lt;br&gt;    addps    xmm1, xmm0&lt;br&gt;    movaps    XMMWORD PTR $T20497[ebp], xmm1&lt;br&gt;    movaps    xmm0, XMMWORD PTR $T20497[ebp]&lt;br&gt;    mov    edx, DWORD PTR _pOut$[ebx]&lt;br&gt;    movaps    XMMWORD PTR [edx], xmm0
    mov    eax, DWORD PTR _pOut$[ebx]&lt;br&gt;    fld1&lt;br&gt;    fstp    DWORD PTR [eax+12]&lt;/pre&gt;&lt;p&gt;Jak widać, kompilator utworzył znacznie mniej kodu. Pierwsze cztery linijki zapisują przekazane wektory do odpowiednich rejestrów SSE (xmm0, xmm1). Następnie addps dodaje te wektory (zwróćmy uwagę – jedno polecenie dodaje po cztery wartości dla każdego rejestru). Kolejne operacje dotyczą zapisania wyniku w przekazanej zmiennej, zaś trzy ostatnie przypisania wartości 1.0 dla ostatniej komórki tablicy. Tak utworzony kod jest zdecydowanie bardziej wydajny od poprzedniego. Widzimy tu zgodne z oczekiwaniami wykorzystanie instrukcji SSE (movaps, addps). Można zapisać to jeszcze lepiej?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. Inline asembler  &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Została nam ostatnia opcja: bezpośrednia wstawka asemblerowa. Wbrew pozorom nie będzie to trudne zadanie – jak już wyżej było pokazane, dodawanie to zaledwie jedna instrukcja.&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: maroon&quot;&gt;void &lt;/span&gt;addVectors(Vector &amp;amp;v1,Vector &amp;amp;v2, Vector *pOut){&lt;br&gt;&lt;span style=&quot;color: maroon&quot;&gt;    _asm&lt;/span&gt;{&lt;br&gt;        mov eax,v1;&lt;br&gt;        mov ecx,v2;&lt;br&gt;        movaps xmm0, [eax];&lt;br&gt;        addps xmm0,[ecx];&lt;br&gt;
        mov eax, pOut;&lt;br&gt;        movaps [eax],xmm0;&lt;br&gt;    }&lt;br&gt;     pOut-&amp;gt;data[&lt;span style=&quot;color: blue&quot;&gt;3&lt;/span&gt;] = &lt;span style=&quot;color: blue&quot;&gt;1.0f&lt;/span&gt;;&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Pierwsze dwie instrukcje przenoszą adresy (warto zauważyć, że wejściowe wektory przekazywane są przez referencje) danych na do odpowiednich rejestrów. Następnie movaps przenosi do rejestru xmm0, to co znajduje się pod adresem wskazywanym przez rejestr eax. Instrukcja addps dodaje zawartość rejestru xmm0 oraz miejsca w pamięci wskazywanego przez ecx. Ostatnie instrukcje zapisują wynik w wyjściowej zmiennej pOut.&lt;/p&gt;&lt;p&gt;Kod, który da nam kompilator, będzie praktycznie identyczny z tym znajdującym się&amp;#160; wewnątrz bloku _asm{}. Dodatkowo dojdzie jeszcze ostatnie przypisanie dla data[3].&lt;/p&gt;&lt;p&gt;Jak widać okazaliśmy się lepsi od kompilatora. ;)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Co więc wybrać?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Pytanie nie jest taki proste. Nie zawsze bowiem, mamy chęć i czas by pisać kod w asemblerze – funkcje operujące na macierzach są zdecydowanie bardziej skomplikowane. Wyniki jakie dają metody z rodziny _mm* są wystarczająco zadawalające, jednak czasem można zaoszczędzić kilka instrukcji, pisząc niskopoziomowo. Dodatkowo funkcję lub metodę można oznaczyć jako inline lub __forceinline, dzięki temu ciało funkcji będzie wstawiane bezpośrednio w miejsce wywołania. Dzięki temu można uniknąć dodatkowego narzutu. Korzystanie z asemblera ma jednak jedną zasadniczą wadę. Funkcje napisane w taki sposób nie są w żadne sposób optymalizowane. Kompilator grzecznie wklei kod, który wcale nie będzie musiał być wykonywany. W takich przypadkach zdecydowanie bezpieczniej jest użyć intrinsic.&lt;/p&gt;&lt;p&gt;Ostatnim dylematem, może okazać sie potrzeba pisania własnych metod obsługi wektorów i macierzy. Jeśli korzystamy z DirectX, mamy tam do dyspozycji funkcje z rodziny D3DX, które (choć nie wszystkie) zostały odpowiednio już przygotowane – optymalizacja normalizacji wektorów lub mnożenia macierzy jest na prawdę dobrze wykonana.&lt;/p&gt;
&lt;/p&gt;</description><link>http://msemegen.blogspot.com/2009/01/kompilator-vs-inline-asembler_06.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item></channel></rss>