{"id":2747,"date":"2020-06-12T12:54:24","date_gmt":"2020-06-12T09:54:24","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=2747"},"modified":"2024-12-16T22:32:27","modified_gmt":"2024-12-16T19:32:27","slug":"%d1%81%d0%ba%d0%b5%d0%bb%d0%b5%d1%82%d0%bd%d0%b0%d1%8f-%d0%b0%d0%bd%d0%b8%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d1%87%d0%b0%d1%81%d1%82%d1%8c-2-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%8f-%d0%bd","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/pt\/2020\/06\/12\/%d1%81%d0%ba%d0%b5%d0%bb%d0%b5%d1%82%d0%bd%d0%b0%d1%8f-%d0%b0%d0%bd%d0%b8%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d1%87%d0%b0%d1%81%d1%82%d1%8c-2-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%8f-%d0%bd\/","title":{"rendered":"Anima\u00e7\u00e3o esquel\u00e9tica (Parte 2 &#8211; hierarquia de n\u00f3s, interpola\u00e7\u00e3o)"},"content":{"rendered":"<p>Continuo descrevendo o algoritmo de anima\u00e7\u00e3o do esqueleto conforme ele \u00e9 implementado no Flame Steel Engine.<\/p>\n<p><strong><em>Como o algoritmo \u00e9 o mais complexo de todos que implementei, podem aparecer erros nas notas sobre o processo de desenvolvimento. No artigo anterior sobre esse algoritmo, cometi um erro; o array de ossos \u00e9 transferido para o shader para cada malha separadamente, e n\u00e3o para o modelo inteiro.<\/em><\/strong><\/p>\n<h3>Hierarquia de n\u00f3s<\/h3>\n<p>Para que o algoritmo funcione corretamente \u00e9 necess\u00e1rio que o modelo contenha uma conex\u00e3o entre os ossos entre si (gr\u00e1fico). Vamos imaginar uma situa\u00e7\u00e3o em que duas anima\u00e7\u00f5es s\u00e3o reproduzidas simultaneamente \u2013 &#8211; pule e levante a m\u00e3o direita. A anima\u00e7\u00e3o de salto deve levantar o modelo ao longo do eixo Y, enquanto a anima\u00e7\u00e3o de levantar o bra\u00e7o deve levar isso em considera\u00e7\u00e3o e subir com o modelo enquanto ele salta, caso contr\u00e1rio o bra\u00e7o permanecer\u00e1 no lugar por conta pr\u00f3pria.<\/p>\n<p>Descreveremos a conex\u00e3o dos n\u00f3s para este caso &#8211; o corpo cont\u00e9m a m\u00e3o. Ao elaborar o algoritmo, o gr\u00e1fico \u00f3sseo ser\u00e1 lido, todas as anima\u00e7\u00f5es ser\u00e3o levadas em considera\u00e7\u00e3o com as conex\u00f5es corretas. Na mem\u00f3ria do modelo, o gr\u00e1fico \u00e9 armazenado separadamente de todas as anima\u00e7\u00f5es, apenas para refletir a conectividade dos ossos do modelo.<\/p>\n<h3>Interpola\u00e7\u00e3o na CPU<\/h3>\n<p>No \u00faltimo artigo descrevi o princ\u00edpio de renderiza\u00e7\u00e3o de anima\u00e7\u00e3o esquel\u00e9tica &#8211; \u201cmatrizes de transforma\u00e7\u00e3o s\u00e3o transferidas da CPU para o shader a cada quadro de renderiza\u00e7\u00e3o.\u201d<\/p>\n<p>Cada quadro de renderiza\u00e7\u00e3o \u00e9 processado na CPU; para cada osso da malha, o mecanismo recebe a matriz de transforma\u00e7\u00e3o final usando interpola\u00e7\u00e3o de posi\u00e7\u00e3o, rota\u00e7\u00e3o e zoom. Durante a interpola\u00e7\u00e3o da matriz \u00f3ssea final, uma passagem \u00e9 feita atrav\u00e9s da \u00e1rvore de n\u00f3s para todas as anima\u00e7\u00f5es de n\u00f3s ativos, a matriz final \u00e9 multiplicada pelas matrizes pai e, em seguida, enviada para renderiza\u00e7\u00e3o ao sombreador de v\u00e9rtice.<\/p>\n<p>Os vetores s\u00e3o usados \u200b\u200bpara interpola\u00e7\u00e3o de posi\u00e7\u00e3o e a amplia\u00e7\u00e3o \u00e9 usada para rota\u00e7\u00e3o, porque; eles s\u00e3o muito f\u00e1ceis de interpolar (SLERP), ao contr\u00e1rio dos \u00e2ngulos de Euler, e tamb\u00e9m s\u00e3o muito f\u00e1ceis de representar como uma matriz de transforma\u00e7\u00e3o.<\/p>\n<h3>Como simplificar a implementa\u00e7\u00e3o<\/h3>\n<p>Para facilitar a depura\u00e7\u00e3o do vertex shader, adicionei uma simula\u00e7\u00e3o do vertex shader na CPU usando a macro FSGLOGLNEWAGERENDERER_CPU_BASED_VERTEX_MODS_ENABLED. O fabricante de placas de v\u00eddeo NVIDIA possui um utilit\u00e1rio para depurar c\u00f3digo de shader Nsight, talvez ele tamb\u00e9m possa simplificar o desenvolvimento de algoritmos complexos de shader de v\u00e9rtices\/pixels, mas nunca consegui testar sua funcionalidade. A simula\u00e7\u00e3o na CPU foi suficiente.<\/p>\n<p>No pr\u00f3ximo artigo pretendo descrever a mistura de m\u00faltiplas anima\u00e7\u00f5es e preencher as lacunas restantes.<\/p>\n<h3>Fontes<\/h3>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=f3Cr8Yx3GGA\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.youtube.com\/watch?v= f3Cr8Yx3GGA<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuo descrevendo o algoritmo de anima\u00e7\u00e3o do esqueleto conforme ele \u00e9 implementado no Flame Steel Engine. Como o algoritmo \u00e9 o mais complexo de todos que implementei, podem aparecer erros nas notas sobre o processo de desenvolvimento. No artigo anterior sobre esse algoritmo, cometi um erro; o array de ossos \u00e9 transferido para o shader<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/pt\/2020\/06\/12\/%d1%81%d0%ba%d0%b5%d0%bb%d0%b5%d1%82%d0%bd%d0%b0%d1%8f-%d0%b0%d0%bd%d0%b8%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d1%87%d0%b0%d1%81%d1%82%d1%8c-2-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%8f-%d0%bd\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Anima\u00e7\u00e3o esquel\u00e9tica (Parte 2 &#8211; hierarquia de n\u00f3s, interpola\u00e7\u00e3o)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[49,61,52],"tags":[],"class_list":["post-2747","post","type-post","status-publish","format-standard","hentry","category-blog","category-techie","category-tutorials","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"pt","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2747","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=2747"}],"version-history":[{"count":9,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2747\/revisions"}],"predecessor-version":[{"id":3912,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2747\/revisions\/3912"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=2747"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=2747"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=2747"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}