Space-Project/zadanie.html
2021-01-16 17:11:39 +01:00

134 lines
13 KiB
HTML

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zadanie</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="style.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="wstęp">1 Wstęp</h1>
<p>Celem tych zadań jest zapoznanie się z biblioteką assimp służącą do wczytywania modeli 3d w różnych formatach.</p>
<p>Projekt VS do nich dołączony jest dobrym punktem wyjścia do zaczęcia projektu zaliczeniowego, ponieważ zawiera wszystkie wymagane biblioteki.</p>
<h1 id="ładowanie-pliku">2 Ładowanie pliku</h1>
<h2 id="export-z-blendera">2.1 Export z blendera</h2>
<p>Internet jest pełen wszelakiej maści modeli 3d (na końcu jest zbiór linków gdzie szukać modeli). Wiele z nich jest dostępnych za darmo, jednak jak to bywa z rzeczami za darmo zazwyczaj nie będą przygotowane pod nasze potrzeby dlatego, trzeba je chociaż w podstawowym zakresie obrobić i wyeksportować do odpowiedniego formatu. W tym celu najlepiej użyć Blendera, który jest darmowy i posiada szeroką grupę pasjonatów udostępniających modele i poradniki za darmo.</p>
<p>W folderze model znajdują się pliki <code>arm.blend</code> oraz <code>arm.fbx</code>. Niestety assimp nie obsługuje plików blend z wersji &gt;2.79 (nie polecam używać blendera poniżej 2.80, interfejs jest wyjątkowo nieczytelny), dlatego modele trzeba eksportować do innego formatu, na nasze potrzeby odpowiedni będzie format <strong>fbx</strong>. Otwórz plik <code>arm.blend</code> w Blenderze (w oknie ładowania pod kołem zębatym jest opcja <strong>load ui</strong> polecam ją wyłączyć, gdy ładujemy nieswoje projekty), zawiera on proste ramie robota. ma ono strukturę hierarchiczną: przykładowo ramie jest dzieckiem kuli, więc jeśli obrócisz kulę, to ramie za nią podąży. Zachowując tą hierarchię będziemy mogli animować ramie za pomocą grafu sceny. Opcja eksportu znajduje się w File-&gt;Export-&gt;FBX, w <strong>Include</strong> w object types zaznacz tylko opcję <strong>Mesh</strong>. Upewnij się, że w zakładce <strong>Transform</strong> opcja <strong>Apply Scalinng</strong> jest ustawiona na <strong>FBX Units Scale</strong>. zapisz plik w folderze models. ## 2.2 Import przez assimp Modele importuje się za pomocą klasy <code>Assimp::Importer</code> i metody <code>ReadFile</code>. Przyjmuje ona ścieżkę do modelu oraz flagi, które określają jakie kroki ma wykonać importer w postprocesingu, może być to obliczenie przestrzeni stycznej czy triangularyzacja. Metoda zwraca wskaźnik na <code>aiScene</code>, jeżeli import się powiódł. Jeżeli nie błąd można pobrać za pomocą <code>importer.GetErrorString()</code>. Zmienna <code>aiScene</code> zawiera dane o scenie, takie jak <em>mesh</em>, informację o materiałach czy hierarchię obiektów w postaci drzewa. Korzeniem drzewa jest <code>scene-&gt;mRootNode</code>. W naszym przypadku <code>RootNode</code> będzie miał jednego syna, czyli <strong>base</strong> w pliku <code>blend</code>, on z kolei będzie miał syna <strong>ball</strong> itd. każdy węzęł zawiera informację o konkretnym modelu jak liczba meshy i ich indeksy w scenie, materiały itd. Przykładowo wczytanie samej bazy będzie wyglądać następująco:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a> Assimp::Importer importer;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="at">const</span> aiScene* scene = importer.ReadFile(<span class="st">&quot;models/arm.fbx&quot;</span>, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace);</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="co">// check for errors</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> (!scene || scene-&gt;mFlags &amp; AI_SCENE_FLAGS_INCOMPLETE || !scene-&gt;mRootNode) <span class="co">// if is Not Zero</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> {</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="bu">std::</span>cout &lt;&lt; <span class="st">&quot;ERROR::ASSIMP:: &quot;</span> &lt;&lt; importer.GetErrorString() &lt;&lt; <span class="bu">std::</span>endl;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span>;</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">auto</span> node = scene-&gt;mRootNode-&gt;mChildren[<span class="dv">0</span>];</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> aiMesh* mesh = scene-&gt;mMeshes[node-&gt;mMeshes[<span class="dv">0</span>]];</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> armContext.initFromAssimpMesh(mesh);</span></code></pre></div>
<p>By przejść po całej scenie potrzebujemy funkcję rekurencyjną <code>loadRecusive</code>, która załaduje meshe z danego węzła, doda je do vectora <code>armContexts</code>, następnie wywoła się dla wszystkich jego synów. Napisz taką funkcję i wyświetl wszystkie obiekty z vectora z macierzą modelu ustawioną na identyczność. Otrzymaliśmy na obiekty, ale są one wyświetlane jeden na drugim, ponieważ nie wczytaliśmy macierzy opisujących ich położenie. Rozwiążemy to w następnym etapie # 3 Graf Sceny Każdy węzeł zawiera atrybut <code>mTransformation</code>, który jest macierzą transformacji względem ojca. By na jej podstawie uzyskać macierz modelu zbudujemy prosty graf sceny. Użyjemy do tego vektora. W <code>RenderUtils.h</code> znajduje się struktura <code>Node</code>, która zawiera: * <code>vector&lt;RenderContext&gt;</code>, w którym będziemy umieszczać dane jego meshy, * macierz modelu * <code>int parent</code>, który będzie zawierał indeks modelu lub -1 jeżeli jest korzeniem.</p>
<p>Przerób funkcję <code>loadRecusive</code>. Dodaj argument parent, w którym będziemy przesyłać rekurencyjnie indeks ojca. Zmodyfikuj tak, żeby każde wywołanie dodawało element do <code>vector&lt;Node&gt; arm</code> i uzupełniał go o meshe, indeks ojca i macierz transformacji. <code>node-&gt;mTransformation</code> ma typ <code>aiMatrix4x4</code>, musisz ją konwertować za pomocą <code>Core::mat4_cast</code>.</p>
<p>Do wyświetlenia wykorzystaj poniższy kod</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> (<span class="kw">auto</span> part : arm) {</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> glm::mat4 transformation=part.matrix;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">int</span> parent = part.parent;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">while</span> (parent != -<span class="dv">1</span>) {</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> transformation = arm[parent].matrix * transformation;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> parent = arm[parent].parent;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> (<span class="kw">auto</span> context : part.renderContexts) drawObject(program, context, transformation, glm::vec3(<span class="fl">0.6</span><span class="bu">f</span>));</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> }</span></code></pre></div>
<h1 id="animacja">4 Animacja</h1>
<p>Dodamy ruch ramienia na klawisze <strong>o</strong> i <strong>p</strong>. By ramie się obracało zgodnie z intuicją wystarczy, że dodamy rotację do kuli (<em>Ball</em>) a graf sceny załatwi resztę. Po pierwsze potrzebujemy znać pozycję kuli w vectorze. Dodaj do <code>loadRecusive</code> sprawdzenie czy nazwa (znajduje się w <code>node-&gt;mName</code>) to <code>aiString("Ball")</code>, jeżeli tak, przypisz do zmiennej globalnej ballIndex indeks węzła w vectorze <code>arm</code>. Pozostaje dodać obsługę przycisków w funkcji <code>keyboard</code>. By wykonać obrót przemnóż od prawej macierz kuli o macierz obrotu o mały kąt. Możesz też wykorzystać wejście myszki i obroty za pomocą kwaternionów z najnowszych ćwiczeń</p>
<h1 id="linki">linki</h1>
<ul>
<li>https://assimp-docs.readthedocs.io/ dokumentacja assimp</li>
<li>https://learnopengl.com/Model-Loading/Assimp tutorial w learnopengl</li>
<li>https://www.blender.org/download/ blender</li>
</ul>
<h2 id="modele-3d">modele 3d</h2>
<ul>
<li>https://www.blendswap.com</li>
<li>https://sketchfab.com</li>
<li>https://www.cgtrader.com/</li>
<li>https://www.turbosquid.com/</li>
<li>https://open3dmodel.com/</li>
</ul>
</body>
</html>