{"id":1501,"date":"2019-01-11T22:20:09","date_gmt":"2019-01-11T22:20:09","guid":{"rendered":"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/?p=1501"},"modified":"2019-01-28T12:27:40","modified_gmt":"2019-01-28T12:27:40","slug":"sterowanie-serwem-za-pomoca-joysticka-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-3-4","status":"publish","type":"post","link":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/?p=1501","title":{"rendered":"Nokia 5510 &#8211; wizualizacja 3D"},"content":{"rendered":"<p>Czy mo\u017cna zmusi\u0107 Arduino do wy\u015bwietlania grafiki 3D? Wiadomo, \u017ce do grania w gry potrzebujemy pot\u0119\u017cnych akcelerator\u00f3w graficznych (karty nVidii lub ATI) lub dla mniej wymagaj\u0105cej grafiki mocnego CPU. Arduino mo\u017ce i nie ma wielkich zasob\u00f3w mocy obliczeniowej, ale przy u\u017cyciu prostego wy\u015bwietlacza i lekkiej imitacji biblioteki 3d mo\u017cemy uzyska\u0107 interesuj\u0105ce efekty. Stworz\u0119 \u201csilnik 3D\u201d &#8211; kt\u00f3ry w zasadzie jest tylko prostym rzutowaniem punkt\u00f3w na ekran. Pomimo ograniczonej funkcjonalno\u015bci, mo\u017cemy uzyska\u0107 ciekawe efekty takie jak obracaj\u0105ca si\u0119 przestrzenna siatka sze\u015bcianu.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1502 size-medium\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0401-300x291.jpg\" alt=\"\" width=\"300\" height=\"291\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0401-300x291.jpg 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0401.jpg 569w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Ca\u0142a sztuczka uzyskania wra\u017cenia 3D polega na dobrym rzutowaniu punk\u00f3w w przestrzeni na piksele ekranu. Wiadomo, \u017ce obiekty dalsze s\u0105 mniejsze, a te bli\u017csze &#8211; s\u0105 wi\u0119ksze (perspektywa!). Ta obserwacja prowadzi mnie do banalnego pomys\u0142u &#8211; nie b\u0119d\u0119 rzutowa\u0107 tr\u00f3jwymiarowych punkt\u00f3w (x,y,z) na ekranik wy\u015bwietlacza (x,y), uwzgl\u0119dniaj\u0105c pozycj\u0119 kamery w przestrzeni a jedynie&#8230; b\u0119d\u0119 zmniejsza\u0107\/zwi\u0119ksza\u0107 obiekty w zale\u017cno\u015bci od ich odleg\u0142o\u015bci! Do oddania efektu g\u0142\u0119bi u\u017cyj\u0119 funkcji wyk\u0142adniczej a nie liniowej &#8211; to kolejna obserwacja, z kt\u00f3r\u0105 trudno si\u0119 nie zgodzi\u0107 (obiekt dwa razy dalej nie jest wcale dwa razy mniejszy!). Dzi\u0119ki temu obiekty znajduj\u0105ce si\u0119 bli\u017cej b\u0119d\u0105 powi\u0119kszane, a te dalej pomniejszane.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1503 size-medium\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/nokia3d-300x167.png\" alt=\"\" width=\"300\" height=\"167\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/nokia3d-300x167.png 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/nokia3d.png 472w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Daje nam to wra\u017cenie, \u017ce obiekty znajduj\u0105ce si\u0119 dalej zbli\u017caj\u0105 lub oddalaj\u0105 si\u0119 wolniej, a natomiast te bli\u017cej &#8211; szybciej. Oddalaj\u0105ce si\u0119 punkty powinny si\u0119 zbiega\u0107 do \u015brodka ekranu aby otrzyma\u0107 efekt perspektywy punktowej.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1505\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0404-297x300.jpg\" alt=\"\" width=\"297\" height=\"300\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0404-297x300.jpg 297w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0404.jpg 561w\" sizes=\"auto, (max-width: 297px) 100vw, 297px\" \/><\/p>\n<p>Jako przyk\u0142ad u\u017cyjemy wy\u015bwietlacza Nokii 5110 oraz bibliotek Adafruit_PCD8544.h oraz Adafruit_GFX.h. Biblioteki pos\u0142u\u017c\u0105 nam do kontrolowania ekranem i wy\u015bwietlania linii.<\/p>\n<p>Na pocz\u0105tku musimy zaimplementowa\u0107 rzutowanie:<\/p>\n<pre class=\"lang:arduino decode:true\" title=\"Punkt 3D\">struct point2D{\r\n int x,y;\r\n};\r\n\r\nstruct point3D{\r\n float x,y,z;\r\n point2D CastTo2D(){\r\n   point2D ret;\r\n   ret.x = szerokosc_ekranu\/2 + (x * X_SCALE *  pow(Z_SCALE, z));\r\n   ret.y = wysokosc_ekranu\/2 - (y * Y_SCALE * pow(Z_SCALE, z));\r\n   return ret;\r\n }\r\n};\r\n\r\n<\/pre>\n<p>Tworz\u0119 w ten spos\u00f3b dwie struktury oraz metod\u0119 do p\u00f3\u017aniejszego rzutowania na ekran. X_SCALE, Y_SCALE to wsp\u00f3\u0142czynnki skalowania na poszczeg\u00f3lnych osiach ekranu (bardzo przydatne w przypadku gdy piksele wy\u015bwietlacza nie s\u0105 kwadratowe). Z_SCALE natomiast to wsp\u00f3\u0142czynnik skalowania g\u0142\u0119bi.<\/p>\n<p>Po pod\u0142\u0105czeniu ekranu do Arduino u\u017cywamy bibliotek, \u017ceby co\u015b wy\u015bwietli\u0107:<\/p>\n<pre class=\"lang:arduino decode:true\" title=\"Test Nokii 5510\">#include &lt;SPI.h&gt;\r\n#include &lt;Adafruit_GFX.h&gt;\r\n#include &lt;Adafruit_PCD8544.h&gt;\r\nAdafruit_PCD8544 disp = Adafruit_PCD8544(5, 4, 3);\r\n\r\nvoid setup() {\r\n    disp.begin();\r\n    disp.display(); \/\/ wyswietlanie buffera\r\n}\r\n<\/pre>\n<p>Ten kr\u00f3tki kawa\u0142ek kodu powinien wy\u015bwietli\u0107 logo Adafruit na ekranie. Mo\u017cna po\u015bwi\u0119ci\u0107 chwil\u0119 na przyjrzenie si\u0119 bli\u017cej bibliotece i postara\u0107 si\u0119 stworzy\u0107 w\u0142asne logo, np. takie:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1507\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0399-300x296.jpg\" alt=\"\" width=\"300\" height=\"296\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0399-300x296.jpg 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_0399.jpg 588w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Gdy ju\u017c wszystko nam dzia\u0142a mo\u017cemy przej\u015b\u0107 do wy\u015bwietlenia czego\u015b przestrzennego. Pomocna b\u0119dzie funkcja rysuj\u0105ca lini\u0119 na ekranie pomi\u0119dzy punktami w przestrzeni:<\/p>\n<pre class=\"lang:arduino decode:true\" title=\"Rysowanie linii z 3D na ekranie 2D\">void draw3DLine(point3D a, point3D b){\r\n disp.drawLine(a.CastTo2D().x, a.CastTo2D().y, b.CastTo2D().x, b.CastTo2D().y, BLACK);\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Musimy jednak mie\u0107 na uwadze w jaki spos\u00f3b punkty przestrzenne s\u0105 konwertowane na piksele ekranu. Punkt (0,0,0) znajduje si\u0119 na \u015brodku ekranu, a sk\u0142adowa Z okre\u015bla powi\u0119kszenie (Z&gt;0) lub pomniejszenie (Z&lt;0) obiektu. Dla Z=0 rozmiar obiektu nie zostanie zmodyfikowany. Znaczenie ma r\u00f3wnie\u017c skala (X_SCALE, Y_SCALE), gdy\u017c to w\u0142a\u015bnie przez te warto\u015bci mno\u017cymy po\u0142o\u017cenie punktu (dla ma\u0142ej skali musimy poda\u0107 wi\u0119ksze wsp\u00f3\u0142rz\u0119dne, bo nasz obiekt na ekranie mo\u017ce okaza\u0107 si\u0119 jedynie ma\u0142\u0105 kropk\u0105).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Wy\u015bwietlenie siatki sze\u015bcianu to odpowiednie po\u0142\u0105czenie o\u015bmiu punkt\u00f3w &#8211; dosy\u0107 proste. Ale jak sprawi\u0107, \u017ceby ten sze\u015bcian si\u0119 obraca\u0142? W tym celu si\u0119gamy po par\u0119 funkcji trygonometrycznych, a mianowicie sinus i cosinus.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1545\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/ang_co-300x205.png\" alt=\"\" width=\"300\" height=\"205\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/ang_co-300x205.png 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/ang_co.png 333w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Zamiast podawa\u0107 konkretne wsp\u00f3\u0142rz\u0119dne x i y, mo\u017cemy u\u017cy\u0107 k\u0105ta i odleg\u0142o\u015bci od \u015brodka. Punkt (r*cos(a), r*sin(a)), niezale\u017cnie od k\u0105ta a, jest zawsze oddalony o odleg\u0142o\u015b\u0107 r od punktu(0,0). Zwi\u0119kszaj\u0105c ten k\u0105t, punkt b\u0119dzie \u201cw\u0119drowa\u0107\u201d po okr\u0119gu. Mo\u017cemy to wykorzysta\u0107 w\u0142a\u015bnie do obracania sze\u015bcianem.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Teraz mo\u017cemy okre\u015bli\u0107 pionow\u0105 par\u0119 punkt\u00f3w wsp\u00f3\u0142rz\u0119dnymi:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">(cos(a)*R, y, sin(a)*R) i (cos(a)*R, -y, sin(a)*R), <\/span><\/p>\n<p><span style=\"font-weight: 400;\">gdzie R to promie\u0144 okr\u0119gu, po kt\u00f3rym b\u0119d\u0105 porusza\u0107 si\u0119 punkty i jednocze\u015bnie po\u0142owa przek\u0105tnej sze\u015bcianu. Aby uzyska\u0107 nast\u0119pn\u0105 par\u0119 punkt\u00f3w musimy je obr\u00f3ci\u0107 o 90 stopni, czyli do poprzedniego k\u0105ta dodajemy \u213c\/2:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">(cos(a+PI\/2)*R, y, sin(a+PI\/2)*R) i (cos(a+PI\/2)*R, -y, sin(a+PI\/2)*R).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">W podobny spos\u00f3b uzyskujemy pozosta\u0142e pary punkt\u00f3w dodaj\u0105c odpowiednio wielokrotno\u015b\u0107 k\u0105ta \u213c\/2 (dla trzeciej pary: 2*PI\/2 i czwartej: 3*PI\/2).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Kiedy ju\u017c zapisali\u015bmy pozycje punkt\u00f3w w tej postaci, mo\u017cemy zwi\u0119ksza\u0107 k\u0105t a (lub zmniejsza\u0107 co spowoduje obr\u00f3t w przeciwnym kierunku). Warto pami\u0119ta\u0107, \u017ce jest to k\u0105t w radianach i nale\u017cy go zwi\u0119ksza\u0107 o stosunkowo ma\u0142e warto\u015bci.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Efekt jest nast\u0119puj\u0105cy:<\/span><\/p>\n<div style=\"width: 720px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-1501-1\" width=\"720\" height=\"405\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/20190120_200335.mp4?_=1\" \/><a href=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/20190120_200335.mp4\">http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/20190120_200335.mp4<\/a><\/video><\/div>\n<p>Kod programu:<\/p>\n<pre class=\"lang:default decode:true\">#include &lt;SPI.h&gt;\r\n#include &lt;Adafruit_GFX.h&gt;\r\n#include &lt;Adafruit_PCD8544.h&gt;\r\n#define Z_SCALE 1.2\r\n#define X_SCALE 20\r\n#define Y_SCALE 16\r\n#define ANGLE 0.08\r\n#define DT 60\r\n#define RADIUS 1.3\r\n\r\nstruct point2D{\r\n  int x,y;\r\n};\r\n\r\nstruct point3D{\r\n  float x,y,z;\r\n  \r\n  point2D CastTo2D(){\r\n    point2D ret;\r\n    ret.x = round(42. + (x * X_SCALE *  pow(Z_SCALE, z)));\r\n    ret.y = round(24. - (y * Y_SCALE * pow(Z_SCALE, z)));\r\n    return ret;\r\n  }\r\n};\r\n\/\/ Software SPI (slower updates, more flexible pin options)\r\n\/\/ pin 7 - Serial clock out (SCLK)\r\n\/\/ pin 6 - Serial data out (DIN)\r\n\/\/ pin 5 - Data\/Command select (D\/C)\r\n\/\/ pin 4 - LCD chip select (CS)\r\n\/\/ pin 3 - LCD reset (RST)\r\nAdafruit_PCD8544 disp = Adafruit_PCD8544(7, 6, 5, 4, 3);\r\n\r\nvoid draw3DLine(point3D a, point3D b){\r\n  disp.drawLine(a.CastTo2D().x, a.CastTo2D().y, b.CastTo2D().x, b.CastTo2D().y, BLACK);\r\n}\r\n\r\nvoid setup() {\r\n  disp.begin();\r\n}\r\n\r\nfloat fi = 0.;\r\nvoid loop() {\r\n\r\n  fi+=ANGLE;\r\n  disp.clearDisplay();\r\n  for(int i=0; i&lt;4; i++){\r\n    point3D a= {cos(i*2*M_PI\/4 + fi)*RADIUS, 1, sin(i*2*M_PI\/4+ fi)*RADIUS};\r\n    point3D b= {cos(i*2*M_PI\/4 + fi)*RADIUS, -1, sin(i*2*M_PI\/4+ fi)*RADIUS};\r\n    draw3DLine(a,b);\r\n    point3D c= {cos((i+1)*2*M_PI\/4 + fi)*RADIUS, 1, sin((i+1)*2*M_PI\/4+ fi)*RADIUS};\r\n    point3D d= {cos((i+1)*2*M_PI\/4 + fi)*RADIUS, -1, sin((i+1)*2*M_PI\/4+ fi)*RADIUS};\r\n    draw3DLine(a,c);\r\n    draw3DLine(b,d);  \r\n  }\r\n  disp.display();\r\n  delay(DT);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: right;\"><em>(c) Bartosz Bytler 2019<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Czy mo\u017cna zmusi\u0107 Arduino do wy\u015bwietlania grafiki 3D? Wiadomo, \u017ce do grania w gry potrzebujemy pot\u0119\u017cnych akcelerator\u00f3w graficznych (karty nVidii lub ATI) lub dla mniej wymagaj\u0105cej grafiki mocnego CPU. Arduino mo\u017ce i nie ma wielkich zasob\u00f3w mocy obliczeniowej, ale przy u\u017cyciu prostego wy\u015bwietlacza i lekkiej imitacji biblioteki 3d mo\u017cemy uzyska\u0107 interesuj\u0105ce efekty. Stworz\u0119 \u201csilnik 3D\u201d [&hellip;]<\/p>\n","protected":false},"author":24,"featured_media":1502,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[52],"tags":[268,267,109,266,16],"class_list":{"0":"post-1501","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","6":"hentry","7":"category-fibot","8":"tag-3d","9":"tag-ekran","10":"tag-grafika","11":"tag-nokia","12":"tag-silnik","14":"post-with-thumbnail","15":"post-with-thumbnail-large"},"_links":{"self":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1501","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1501"}],"version-history":[{"count":5,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1501\/revisions"}],"predecessor-version":[{"id":1555,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1501\/revisions\/1555"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/media\/1502"}],"wp:attachment":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}