1. 今週の予定
今週も予定を見直す時間がありませんでした。ぶっつけ本番でやっていきます。
先週計画した通り、今週から以下の内容を勉強する予定です。
- 映像作品としてのLevelの作成
- AIの勉強
- Nvidia Omniverseの勉強
- Gaeaの勉強
- Houdiniの勉強
- UEFNの勉強
- DirectX12の勉強
これだけ量を減らしたら、余裕をもってそれぞれの課題を余裕をもって勉強出来るはずです。
2. 映像作品としてのLevelの作成
今週はCameraの挙動を修正します。
2.1 Level SequenceのCameraの挙動を変更する
以下のように変更しました。
CameraがDragonがJumpした時に、Dragonを一寸だけ追うようにしました。
結果です。
なんかおかしいです。
CameraがDragonがJumpする前からDragonの上の方を向いています。
DragonがJumpしてからCameraが動くように変更します。
Cameraが上を向くKey Frameを0.3秒ほど後ろにずらしました。
結果です。
Cameraが上を向いたときにもう少しDragonの全体像が入るようにしたいです。
でも前回のCamera Workよりは大分マシになりました。
2.2 修正予定内容のまとめ
これから直したい部分をざっくばらんに以下にまとめておきます。
<Cameraが上を向いたときにもう少しDragonの全体像が入るようにする>
以下に示した様にDragonの姿が半分しか写っていません。
後、今確認した感じではCameraがDragonを追い始めるTimmingはもう少し遅くても良いかもしれません。
<Dragonの足が地面に潜っている>
DragonがJumpする一寸前のDragonの足が地面に潜っています。
これを直します。
地面にPlatを置いてその上をDragonに歩かせたら直るんでしょうか?
<Dragonの足が出てる>
これはDragonのAnimationが途中で終わっているからです。
Dragonが飛ぶAnimationを追加すれば解決するはずです。
<Dragonの色の調整>
Dragonの色と言うかDragonに当たっている光が強すぎます。
この光を弱くして周りの環境に合わせます。
取りあえず思いつくのはこれぐらいです。
2.3 DragonのAnimationの追加
これは今出来るのでやってしまいます。
以下のようにDragonが飛ぶAnimationを追加しました。
結果です。
Dragonの足がダランと垂れるSceneが無くなりました。
これを見るとCameraが上を向くTimmingがまだ早い気がします。
Cameraが上を向いて固定するKey Frameを0.3秒ほど後ろにずらしてみました。
結果です。
うーん。
今度はJumpして宙に浮いているDragonがほとんど見えなくなってしまいました。
今度はCameraが上を向いて固定するKey Frameを0.15秒ほど前に戻してみました。
結果です。
かなりマシになりました。
2.4 Dragonの足の修正方法の検討
以下のようなAnimationを作成しました。
Dragonが歩いているAnimationです。
以下のようになりました。
見事に空中を歩いています。
これを直します。
横から見たらこんなに浮いていました。
Dragonの位置はEnd KeyでFloorに付けたんですが何故、こんな結果になったんでしょうか?
Dragonを選択してEnd Keyを押してもDragonはFloorから浮いたままです。
うーん。
何で?
仕方ないのでAnimationのLocationを弄って直そうとしたら、とんでもなく面倒な事に気が付きました。
代わりにFloorの位置を変更しました。
DragonはFloorの上を歩いているように見えます。
結果です。
まだわずかにDragonの足が浮いています。
原因が判明しました。
以下のようにDragonの足を完全にFloorに付けると
その後のSceneでDragonの爪がFloorより下に移動してしまいます。
こればっかしは元のAnimationがそうなっているので直しようがありません。
いやもしかしたら直せるのかもしれませんが、まだ映像用のAnimationの作成Level1の今の私にはこれを直すのは不可能です。
一応、爪が地面にめり込むVersionのAnimationを以下に示します。
爪が地面に潜っている事なんか全く気になりません。
Dragonの足がしっかり地面についている感じがしています。
やっぱり足の裏の影が見えない事が重要です。
これがあるとすぐに足が浮いている事に気が付きます。
それ以外はあんまり気になりません。
2.5 Dragonの足の修正方法の検討した感想
以下のDragonの足が地面にもぐっている問題をどう直すのかを検討した結果、
Dragonの位置を一個ずつ直すのではなくFloorつまり、この場合は3D Gaussian Splattingの方を移動させる方が楽という事が判明しました。
一寸だけ試してみます。
あれ?
3D Gaussian Splattingが2つあります。
何で?
知らない間にDuplicateしてた。
一個表示しないようにしましたが何も変化しません。
一個は消します。
残った3D Gaussian SplattingのZのLocationを20程さげました。
20cm下がったという事になるはずです。
以下のようになっています。
撮影しました。
結果です。
よーく見ると今度は後ろ脚が浮いていて地面についていません。
でもこれは普通の人は気が付かないかもしれません。
後は空に浮いているDragonを見上げるSceneですが
Dragonが一寸しか写っていません。
まあでもこの辺は来週直す事にします。
今週はこの辺で終わりにします。
3. AIの勉強
3.1 先週の結果を検証する
先週は初めて自分でAIの学習を実行しました。
しかしこの結果の解釈が分かりません。
まずそれから調べますt
Copilotに質問しました。
以下にCopilotの答えを示します。
<Train Loss>
Modelの予想と実際の結果がどれくらい合っているかを示しているそうです。
先週の私の結果は以下のようになっています。
Fine Tuneの結果、0.075まで下がっていますが、最初の結果は0.6970と約7割も間違えています。
Is it a bird? Creating a model from your own data [1]の結果は
となっていました。
うん?
私の結果はIs it a bird? Creating a model from your own data [1]の結果と比較してみると、悪いですが特別悪い訳でもありません。
まあまあの結果でした。
<Validation Loss>
Test様に学習では使用しなかったImageを使用してTestした結果を示してます。
私の結果です。
96%も外しています。
つまり全部外したって事?
逆に凄くない。
Fine Tuneした結果、6%まで下がっていました。
Is it a bird? Creating a model from your own data [1]の結果です。
1%強の割合で外しています。
これぐらいが正しい結果のような気がします。
私のAIは何でこんなに質が悪かったんでしょうか?
Is it a bird? Creating a model from your own data [1]のfine tuneの結果です。
ほとんど変化していません。
1%強の割合で外しています。
先週の私のFine Tuneの結果は以下のようになっていました。
20%から3%の割合で外しています。
うーん。
Fine Tuneの結果、成績はよくはなって来ていますがそれでもIs it a bird? Creating a model from your own data [1]の結果と比較すると非常に悪いです。
<Error Rate>
先週の私の結果です。
前2つの結果が以下のようになっているにも拘わらず、0.24になるのは何故なんでしょう?
Fine Tuneの結果は順当に値が下がっています。
Is it a bird? Creating a model from your own data [1]の結果は以下のようになっていました。
ほとんど0ですね。
<Time>
Trainingに要した時間の事ですね。
先週の私の結果です。
ほぼ0です。
Is it a bird? Creating a model from your own data [1]の結果です。
この結果だけはほぼ同じ結果になりました。
3.2 もう一回計算してみる
先週のAIの学習結果はあまりにも悪いです。
もう一回計算しても同じ結果になるか試してみます。
DuckDuckgo_SearchをDownloadしました。
以下のCodeを実行します。
結果です。
正常に実行されました。
次に以下のCodeを実行します。
今回も4つのErrorが発生しました。
DataBlockを生成します。
結果です。
前回の結果とは違っていますね。
以下に前回の結果を示しておきます。
最後にAI学習するためのVision_Learner()関数を実装します。
実行します。
前回の結果です。
Is it a bird? Creating a model from your own data [1]の結果です。
うーん。
今回の私のAI学習の結果は前回の私のAI学習の結果と大体同じです。
Is it a bird? Creating a model from your own data [1]の結果と比較するとかなり悪い印象を受けます。
取りあえず判断は保留してIs it a bird? Creating a model from your own data [1]のStep3を勉強する事にします。
3.3 Is it a bird? Creating a model from your own data [1]のStep3を勉強する
Step 3: Use our model (and build your own!)を勉強します。
以下の実装を追加します。
結果です。
こんだけでした。
うーん。
じゃまず実際に試してみます。
なんとErrorになってしまいました。
Geminiの回答です。
このSourceに書かれているfastai machine learning model predictions [2]を見ます。
こっちを見ると以下の実装でこの問題を回避出来たとありました。
うーん。
Path()関数でBird.jpgのAddressを調べたら
Bird.jpgと出て来ました。
以下のCodeを実行したら原因が判明しました。
Bird.jpgというFileが存在しない。と言っています。
じゃBird.jpgというFileを作成する必要がある訳です。
前の実装を見ると
以下の実装でBird.jpgというFileを作成していました。
これを実行すればBird.jpgが生成されると思われます。
実行します。
Errorになりました。
Geminiに聞くとDirectに以下の実装を実行してないからじゃない。と言って来ました。
全く同じ実装があったのでこれを実行しました。
その上で以下のCodeをもう一回実行しました。
今度はErrorにならず、以下の結果が表示されました。
そして
もう一回以下の実装を実行しました。
結果です。
はは。
やっと出来ました。
4. Nvidia Omniverseの勉強
4.1 Omniverseを起動する
先週までの勉強でOmniverseがどんなものなのか大体理解しました。
今週は前にDownloadしたOmniverse launcherを起動して前の通りに動くか確認します。
以下のBoxが表示されました。
更にBrowserが開いて以下のLogin画面も表示されました。
うーん。
まずLauncherの方からLoginしていきます。
Browserが開いてPasswordの入力を聞いてきました。
入力しました。
Launcherが開きました。
ここまでやってVirus対策Softが最新のVersionを起動するために再起動して下さい。と表示している事に気が付きました。
途中ですがPCを再起動します。
もう一回Omniverseを開きます。
またBrowserが開いて以下の表示が出て来ました。
あ、分かりました。
これはDriveのLoginのためです。
以下の場所を開くとDriveが起動してない事が確認出来ます。
でもExploreを開くと以下の示した様にLocalhostは起動してはいますね。
DriveはLoginしてないだけで起動はしているみたいですね。
Adminと打ってLoginしました。
NVIDIAのFolderはLockがかかっていますね。
しかも以下の表示も白黒のままです。
うーん。
何で?
Localhostを選択すると
Browserが開いて以下の表示が現れます。
うーん。
100%完璧に動いている感じでは無いですね。
でもまあ一応動くのは確認出来ました。
では早速Isaac Simの勉強をしたいのですが、そこは一寸我慢して
2024-06-23のBlogで勉強したOmniverse Createの勉強を先にやる事にします。
4.2 Setting Up A Project in NVIDIA Omniverse Create Part 1: Getting Started [3]を実装する
Omniverse Createは既にInstallしているので
Launchを押してみます。
以下の画面が開きました。
2024-06-23のBlogの説明と全く同じ画面です。
Createを選択して以下のBoxを開き
Planeを選択します。
Planeが追加されました。
Blogの説明だと、Tutorialではここで「移動、回転、拡大縮小のやり方」を説明したみたいです。
でもBlogにはそのやり方は書いてありませんでした。
勝手にやり方を解明します。
分かりました。
左側にある以下のToolbarの以下のIconを選択します。
以下のGismoが表示されました。
矢印かSquareを選択するとPlaneを前後左右上下に移動出来るようになりました。
以下のIconがRotationで
以下のIconがScalingでした。
はい。
解決しました。
Cubeも追加してみました。
この後、このTutorialではSlot MachineのAssetを追加しています。
が、勿論このAssetを持っていないので
ここで終わりにします。
最後にProjectのSaveの仕方だけ勉強します。
Fileを選択してSaveを押すと
以下のWindowが開きます。
当然、LocalhostにSaveしたいんですがどうやったら良いんでしょうか?
Localhostを選択します。
Project内に新しいFolderを作成しました。
このFolderを選択してSaveを押します。
以下のBoxが表示されました。
うーん。Saveは失敗したみたいです。
うーん。
Save出来ません。
諦めてCreateを閉じようとしたらSaveしますか。って聞いてきました。
Yesを選択したらなんかSaveしたみたいな挙動を示しました。
もう一回CreateをLaunchして確認します。
何もSaveされていませんでした。
うーん。
何で?
まあ良いです。
Saveのやり方は来週勉強する事にします。
今週のOmniverseの勉強はここまでとします。
5. Gaeaの勉強
今週はGaea2.0の公開に従って、GaeaのTutorialのこれからについて解説します。
5.1 PowerPointの作成
以下のように作成しました。
今回のLectureの内容を簡単に説明しています。
Gaea2.0の現時点で判明している情報と、これからこのTutorialをどうするのかについての説明をする事を言っています。
今回のTutorialを作成するに当たって、参照にしたSiteやYouTubeのChannelを紹介しています。
Gaea2.0で最も重要と思われる情報の内、どんな情報を得る事が出来たのかを簡単に説明しています。
Community Edition(無料版)があるのかどうかについての情報です。
Community Editon(無料版)についての情報です。
Gaea2.0では商業利用が禁止されています。
Gaea1がDownload出来なくなったことについて紹介しています。
ここが重要なんですが、これらの情報を得た結果、このTutorialのこれからをどうするかについて語っています。
まずGaea1のTutorialをここで作り続ける意味は無いです。
次にGaea2のTutorialを新しく作成する意義がある事を確認しています。
のでGaea2のTutorialを新しく作成する事にした事を説明しています。
そして今度、Tutorialを作成するに当たって、もっと質を上げて量を減らしていきたいという事も述べています。
まとめです。
最後にGaea2.0を一寸だけいじった感想も述べています。
6. Houdiniの勉強
Rick Banks氏のCastle Wall Toolの復習をします。
6.1 Resampleノードの機能を調査する
先週のBlogの最後に以下のように書いてありました。
これからやっていきます。
先週のBlogを見るとResampleノードを以下の場所に追加する事で
以下の結果を
以下のようにしました。
しかしこの結果は、
敢えてResampleノードを使用しなくても
以下に示した様にLineHeightノードのPointsの値を
増やすだけで
以下に示した様に同様の結果を示す事が出来ます。
しかしこのTutorialでは敢えてResampleノードを追加してこの形状を作成しています。
つまりこの2つの結果は実際はどこかが違うという事です。
そのどこかをはっきりさせるのが今回の勉強の目的です。
LineWidthノードのPointの値を5に増やすと
横線のPointの数が5に増えて、以下に示した結果になります。
LineWidthノードのPointは5の状態のままで、LineHeightノードのPointの数を2に戻し
Resampleノードを追加すると
以下のようになりました。
あれ?
変わってないじゃん。
先週、確認した時はPrimitiveの数が増えてたと思ったんですが。
うーん。
ResampleノードのLengthの値を変更してみました。
0.1だったのを1に変更しました。
結果です。
LineHeightノードのLengthの値は5だったので
0、1、2、3、4、そして5の位置に新たにPointが生成されています。
つまりそれぞれのPointの間が1になっています。
ResampleノードのDocumentを調べます。
Nodeの機能を調べる方法は色々勉強しましたが、覚えていません。
Googleで検索します。
有りました。
公式SiteのResample geometry node [4]です。
CurveやSurface上の表面を均一な長さで分割し、それに基づいてSampleを取り直す機能だと言っています。
うーん。
成程。
このResampleの前に書かれている図がこのNodeの機能を一目で表しています。
成程ね。
こういう時にResampleノードが活躍するのか。
となると今回の場合は、Resampleノードを使用しなくてもLineHeightノードのLengthの値を変更したら同じ結果になるって事になりました。
うーん。
先週の予測とは違った結果になりましたが、こういう事もあるでしょう。
公式SiteのResample geometry node [4]を読んでいたら以下の文章がありました。
このExampleはHoudiniからこのDocumentを開かないと見れないみたいです。
うーん。HoudiniからNodeのDocumentを開く方法を調べます。
簡単に判明しました。
Parameter Paneにある以下のIconを押すだけです。
以下のWindowが開きました。
さっきのNetで見た公式のSiteとまったく同じ内容です。
Exampleまで来ました。
Loadを押します。
Network Paneの表示が以下のように変わりました。
よく見るとScene Viewも以下のように変化していました。
これは今までの実装に、新たにNodeが追加されたみたいです。
一個上の階層に戻ってみると以下のようになっていました。
ResampleLines1ノードが新たに追加されていました。
ResampleLines1ノードを開き、中にあるNodeを一個づつ見ていきます。
Even_length_segments_along_arcsノードです。
Scene ViewのImageです。
うーん。
このNodeはResampleノードの名称を変更しただけなはずです。
なんでLineを描く事が出来るんでしょうか?
Even_length_segments_along_arcsノードを開いてみます。
あ、Resampleノードがありました。
Polygon Curveノード、Nurbs Curbノード、そしてBeizer CurbノードをMergeノードで一つにして
Resampleノードに繋いていました。
それぞれのCurveのPointがどのようにResampleされたのかを確認します。
PolygonノードのPointsです。
これは最初から等分に分割されています。
Resampleノードの結果です。
あれ?
Pointの数が変化しているだけでなく、Curveの形状そのものが変化しています。
以下のResample by Polygon EdgeにCheckを入れると
以下のようにCurveの形状を保ったままResampleしました。
Resampleノードの脇にあるComment欄では、
Resampleノードの以下に示したParameterであるMeasureのAlong Arcの機能について解説してありました。
以下のように解説しています。
元々のCurveを定義するのに使用したPointsを利用してResampleするように指定している。と言う事のようです。
うーん。
それが分かったとしても感覚的にどうやってPointを振り直しているか想像する事は無理ですね。
あんまり意味のない解説でした。
Measureを開くとAlong Arcの他にAlong Chordと言う値があります。
ありますが、こっちはResampleする時にAlong Arcと比較してどう違うのかは述べていません。
と思ったらこっちのSampleがAlong Chordを使用した場合を説明していました。
成程。
そう言う事なのか。
このLoadで出て来た具体的な例を使用したNodeの説明は非常に分かり易いです。
これは金脈を発見したかもしれません。
Even_length_segments_along_chordノードを開きResampleノードのComment欄を見ます。
以下の説明がありました。
Maximum Segment Lengthはこれです。
このParameterしか使用出来ないってどういう事でしょうか?
分かりました。
Measureの値をAlong_Chordにした場合は、Segmentの数に応じてなるだけ元のCurveの形状を再現する方向でResampleされるそうです。
つまりSegmentの数が多ければ多いほど、元のCurveが再現される訳です。
Segmentの数を指定するのはMaximum Segment Lengthです。
つまりこのParameterの値さえ定義したら後のParameterは定義する必要はあんまりないって事を言ってると思われます。
「Parameterしか使用出来ない」ではなくて、「このParameterしか使用する必要が無いかもしれない。」と言っていたんです。
成程。
残り2つのSampleはMax_Segment_LengthとMax_number_segmentについて解説しているようです。
これも興味深いので見る事にします。
これしか説明がなかったです。
Aminationってどうやって見る事が出来るんでしょうか?
Max_number_segmentのSampleも見てみます。
こっちのResampleノードのParameterを見ると以下のように
Max_Segmentsが選択されていました。
こっちもResampleノードのComment欄に以下の解説がありました。
うーん。
ここで「the segments span from start to endpoint but are scaled equally in order to fit the desired number across the curve.」と言っていますが、
別に均等にSegmentを割り振るのはMax_Segment_Lengthでも同じじゃない。と思いました。
そうだ以下の実験をすれば違いが確認出来るかもしれません。
以下の実装を組みます。
Lineは以下のような設定にしました。
ResampleノードでMax_Segment_LengthとMax_Segmentsの両方を試してみます。
Max_Segment_Lengthです。
Lengthの長さを0.8にしました。
結果です。
Lineの長さが5なので、5÷0.8=約6です。
8個のPointが生成されています。
それぞれのLengthの長さを調べると
以下のようになっていました。
0.8と指定したにも関わらず実際は0.71になっていました。
つまり0.8に最も近い値でCurve(この場合はLine)を均等に分割する値が自動で選択されています。
今度はMax_Segmentsを選択した場合です。
Segmentの値には7を指定しました。
結果です。
Line上に0から7のPointが均等に生成されています。
Segmentの値を10にしました。
今度はLine上に0から10のPointが均等に生成されています。
はい。
これで(少なくとLine上における)Max_Segment_LengthとMax_SegmentsのPointの生成方法の違いが判明しました。
Max_Segment_LengthはPoint同士の距離を指定します。
ただしLineを均等に分割する必要があるので、指定した値がそのまま採用されるのではなく、指定した値から最も近いLineを均等に分割出来る値が自動で選択されます。
Max_Segmentsの場合は指定した値+1でLineを均等に分割します。
それだけの違いでした。
理解したらこれらの機能は簡単でした。
しかしMax_Segment_LengthとMax_Segmentsの理解と比較するとAlong ArcとAlong Chordの違いはよく分からないですね。
この2つの違いについて別な方法で調査します。
Copilotに聞きました。
以下の回答が返って来ました。
うーん。
分かり易い。
Along ArcはSegmentの長さだけでなくCurve全体の形状も考慮してResampleするのに対して、Along ChordはResampleするに当たってSegment Lengthだけしか考慮しません。
こういう解答が欲しかった。
更に以下の解説がついていました。
Along Arcの説明で出て来たHull InformationとはCurveの全体像に関する情報だそうです。
Along Arcでは以下の2つのParameterを指定する事でResampleの状態を決定する事が出来るそうです。
何でLengthとNumberを同時に指定出来るんでしょうか?
LineではないCurveの場合はそう言う事が出来るんでしょうか?
ここは一寸理解出来ないですね。
それに対してAlong Chordは以下の解説が追加されていました。
うーん。
この辺はまだよく分からないです。
7. UEFNの勉強
先週のBlogの最後に以下のように書いてありました。
7.1 Classの生成方法とObjectの生成方法
この2つだけは最初に調べてしまいます。
公式SiteのClass [5]にClassの作成方法が紹介されていました。
これはまっさらな状態でClassを生成する方法ですね。
最初にPropertyを定義しています。Constant型とVariable型の2つの定義をしています。
その後でこのClass特有のFunctionを定義していますね。
この説明は簡単で理解しやすかったんですが、次の以下の例が中々理解出来ませんでした。
これは
EffectsをClassのMemberの定義に使用しても良い事をこの実装で示しています。
ここで言うEffectsとはSpecifiersの事です。
しかしSpecifiersの指定で使用する<>がここにはありません。
例えばSuspendsであるFunctionは以下のように<Suspends>を使用して以下のように定義しています。
しかしこの例にあるMethodの定義は
これで終わっています。
どこにも<>が使用されていません。
これでどうやって<>を定義しているんでしょうか?
よく分からなかったです。
解説をよく読んだら以下のように説明していました。
ここにあるHeadTiltの値を定義している関数、IdentityRotation()はSpecifierである<converges>を使用して定義されているそうです。
その結果、HeadTiltも<converge>を使用して定義されたのと同じになるそうです。
やっとこの例の意味が判明しました。
一応、IdentityRotation function() [6]のSiteも確認のため見ておきます。
以下のように定義されていました。
あれ?
<native>と<public>が使用されていて<converge>なんか使用されていません。
うーん?
Specifiers and Attributes [7]の
Convergesの定義を読むと
NativeはConvergesの一種のように書かれている感じがします。
がざっと読んだだけでははっきりとは言えません。
今はClassの作成方法について調べているので、Specifierの定義について更に調べる事は出来ないです。
Specifierの定義は来週調べる事にします。
Class [5]の勉強に戻ります。
今度はClassからInstanceを作成する方法が紹介されていました。
このやり方は知っています。
後、勉強する必要があるのは既存のClassを継承して新しいClassを作成する方法です。
Class [5]のSubclasses and Inheritanceにそのやり方が載っていました。
ここではClass、PetをInheritanceしてCat ClassとDog Classを作成しています。
うん。
Classの作成方法とClassからInstanceを生成する方法、そしてClassを継承して新しいClassを作成する方法は、大体理解しました。
7.2 先週のBlogを復習する
まずこれです。
Class、NPC_BehaviorをInheritanceして新しいClass、my_first_npc_behaviorを作成しています。
しかし本来ならこの後にこの新しく生成したmy_first_npc_behaviorに追加するMemberの表記が続くはずです。
先週のBlogではその部分は完全に抜けていました。
UEFNを開いて確認します。
ああ。
Fortniteがメンテ中で開けません。
うーん。
仕方ない。VS Codeだけ開きます。
開けましたがなんかErrorになっています。
まあ、今週はCodeを確認するだけなので問題ないです。
はい。
何と今まで書いていたCodeは全部、my_first_npc_behaviorに追加するMemberの表記でした。
以下のFieldが追加されています。
更にmy_first_npc_behaviorの親Classであるnpc_behavior のMethodであるOnBegin()関数も、以下のようにOverrideされていました。
はあ。
そう言う事だったのね。
今まで、こういう事をしてたのか。
納得しました。
次は以下に示したDebugDraw型のObjectであるDebugDrawNPCの生成についてです。
まず左辺の以下の部分は
DebugDraw型のObject、DebugDrawNPCを宣言しています。
そしてこの実装の右辺である
はその宣言されたDebugDrawNPCを初期化しています。
Class [5]では以下の例が紹介されていました。
うーん。
すこしだけ書き方が違いますね。
そう言えば昔、VerseのObjectの初期化のやり方が2つあった事を勉強した記憶があります。
過去のBlogをあさってみます。
見つかりません。
本当に見つからないのは滅多にないんですが、見つからないです。
公式ForumのInstantiating a struct in Verse [8]でStructですが以下の例を見つけました。
この例ではCoordinate型のObjectであるTestを=を使用して初期化しています。
DebugDrawNPCの生成と同じやり方です。
Debug_Drawの後のCurly Brace内にこのClassのMemberの値を指定しています。
この例ではChannelの値だけ指定しています。
Debug_Draw ClassのMemberってDrawしかないんでしょうか?
Debug_Draw ClassのMemberを復習します。
中々見つからなかったですが、Moduleの分類から蔦って見つけました。
debug_draw class [9]です。
FieldのMemberは以下に示したDebug_Draw_Channel型のChannelしかなかったです。
VerseではFieldのMemberの事をDataと呼ぶのか。
これからはDataもしくはData Memberと呼ぶ事にします。
後Channelの初期化の方法を以下のようにやっています。
うーん。
Channel = my_first_npc_behavior_debug_draw
ではないのか?
=ではなく:=を使用しています。
これは後で調べる事にします。
先週のBlogの続きを読みます。
Debug Draw Classについて調べていました。
うーん。
でも先週の時点ではVerseにおけるClassの生成方法を忘れてしまったので、あんまり理解して勉強して無いです。
そして以下のように書いていました。
これを理解するのか。
うーん。
これは来週やる事にします。
今週はここまでとします。
8. DirectX12の勉強
8.1 Lötwig Fusel氏のD3D12 Beginners Tutorial [D3D12Ez]を勉強する
8.1.1 SwapChain | D3D12 Beginners Tutorial [D3D12Ez] [10]の最後の10分を勉強する
先週、DXGI_SWAP_CHAIN_DESC1型のStructであるswdの設定が終わりました。
のでCreateSwapChainForHwnd()関数に使用するもう一つのStrctである
の設定を指定します。
何と、これだけでした。
うーん。
そうなのか?
そしてShutdown()関数にSwapChainをReleaseするための実装を追加します。
DXWindowのH Fileの方に新しい関数、Rreset()を追加します。
この関数内でSwapChainに何をやるかを指定します。
そしてWindow Cpp Fileに以下の実装を追加しました。
Present()関数のそれぞれのParameterについても、Tutorialでは簡単な説明をしていましたが、あまりにも細かい内容になるのでここでは無視します。
そしてMain()関数内の以下の場所に
Preset()関数を追加しました。
この状態で実行すると以下のようにWindow内が黒くなります。
これはWindowのSizeを変えても変わらないです。
あるSoftを使用してこのWindowにVido Cardの状態を表示しています。
すると数字が変化しても前に表示された数字が消えてない事が判明します。
この画面をClearする機能をこれから追加するそうです。
更にこの実行を停止するとErrorになりました。
このErrorも直します。
Errorの原因をDebug Layerが報告しています。
このErrorの原因について更に詳しくTutorialで解説しています。
この解説は複雑なので、まずこのErrorを直すための実装だけ以下にまとめます。
Main関数の以下の場所にFlushingを追加します。
そしてWindow.cppに以下の実装を追加します。
作成したBufferの数を返す関数ですね。
SwdのBufferCountの値を直しました。
ここでこの値を直していたのか。
更に以下の実装をDXContent.h fileに追加します。
こっちはInlineで実装するんですね。
Inlineを使用すべき時ってどういう時なんでしょう?
Copilot先生によると以下の条件の時にInlineを使用せよ。と言っていました。
三番目の条件だけが私が使用しそうな場合です。
これだけ覚えておきます。
先程作成したFlushingに以下の実装を追加します。
テストしています。
実行を停止してもErrorが起きなくなりました。
その代り以下のWarningが出て来ました。
この警告を消すために、DXContent Cpp FileのShutdown()関数に以下の実装を追加しました。
警告は消えました。
何と、Tutorialはここで終わってしまいました。
文字を消す実装は次のTutorialでやるみたいです。
8.1.2 Errorの原因の説明をまとめる
先程、Tutorialで実行を停止すると表示されるErrorの原因の説明が複雑なので端折ってしまいました。
その内容は結構重要だと思うのでここにまとめておきます。
Tutorialの28分10秒位からErrorの原因の説明が始まっています。
まずDebug LayerのMessageです。
Tutorialではサラッと説明して流してしまって、ここに何が書かれていたのか全然読めませんでした。
のでScreenshotを連続で取って確認します。
以下に区切ってまとめ直しました。
D3D12 ERROR: ID3D12Resource2::<final-release>: CORRUPTION:
An ID3D12Resource object (0x000002811C8DFD0: ‘Unnamed Object’) is reference by GPU operations in-flight on Command Queue(x00000281166C88C0:’Unnamed ID3D12CommandQueue Object’).
It is not safe to final-release object that may have GPU operations pending. This can result in application instability.
[ EXECUTION ERROR #921: OBJECT_DELETED_WHILE_STILL_IN_USE]
訳するとこんな感じですか。
名前の無いID3D12Resource object(0x000002811C8DFD0)がCommand QueueからReferenceされています。
Command QueueからReferenceされているObjectがあるという事はGPUの操作中である可能性がある。
のでこのObjectをReleaseするのは安全ではない。
この行為はApplicationが不安定になる結果になるかもしれない。
って感じですか。
成程。
という事はCommand Queueの実行を先に停止すれば良いという事です。
ここからTutorialの説明になります。
TutorialではこのErrorの原因は、以下のDXWindow ClassのShutdown()関数内で
SwapChainをReleaseしているからだ。と説明しました。
それはそうですが、SwapChainは結局どこかでReleaseしないといけないのでは?と思いました。
その後で、分かり易い説明がありました。
このSwapChainは、Releaseする時に、
- Two Buffer
- Two ID
- Three Digital Resource
を保持したままです。
SwapChainをReleaseすると、これらの保持していたDataも同時にReleaseされます。
しかしここにあるResourceはCommand QueueからもReferenceされています。
ここの説明が今一理解出来なかったんですが、以下の内容を言いたかったのだと思います。
- Command QueueがまだGPUと仕事をしているのに、SwapChainがそのCommand Queueが使用しているResourceを消してしまっています。
- これがErrorの原因です。
この問題を解決するのは簡単だそうです。
SwapChainをReleaseする前にCommand QueueをFlushすれば良いそうです。
うーん。
納得。
ここでMain.cppにFlushingを追加しました。
ところがこの実際の実装が、想像しているのの10倍位複雑でした。
まず動いている全てのCommand QueueをFlushする必要があります。
Command Queueは複数作成されているので作成された全てのCommand Queueを一つずつFlushする必要があるそうです。
更に、実際にCommand QueueをFlushするには、Signalを使用する必要があるそうです。
つまり作成された全てのCommand Queueを一つずつFlushするために、Signalを何回も発する必要があるという事です。
うーん。
複雑。
そして以下の関数をDX Content.h file内に作成しました。
ここで使用されているSingalAndWait()関数は以下に示した様に
Command QueueのSingal Eventを発し、FenceにSignalが発するまで待つように指示する関数です。
うーん。
全く覚えていません。
そう言う事にして先の説明を聞きます。
以上でした。
8.2 「DirectX 12の魔導書」を勉強する
8.2.1 先週の復習をする
先週は「5.2 Vertex情報にUV情報を追加する」を勉強する途中で、Sample Codeを実行するには、DirectXTexをInstallする必要がある事を知って、NuGetを使用してProjectにNuGetをInstallしました。
しかしProjectからDirectXTexを参照する事は出来なかったです。
何故か不明なままで終わってしまいました。
その後で、教科書の「5.11 画像Fileを読み込んで表示する」にどうやってDirectXTexをInstallするのかの詳しい説明がある事を知りました。
その後で、「5.2 Vertex情報にUV情報を追加する」の残りを勉強しました。
8.2.1「5.2 Vertex情報にUV情報を追加する」を実装する
Struct Vertexを作成します。
このVertexに基づいてVerticesの設定を変更します。
しました。
最後にVertMapの型をVertex*に直しました。
以上でした。
9. まとめと感想
なし
10. 参照(Reference)
[1] Jhoward. (2022, August 15). Is it a bird? Creating a model from your own data. Kaggle. https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data
[2] fastai machine learning model predictions. (n.d.). Stack Overflow. https://stackoverflow.com/questions/75698634/fastai-machine-learning-model-predictions
[3] NVIDIA Studio. (2022, January 8). Setting up a project in NVIDIA Omniverse Create Part 1: Getting started [Video]. YouTube. https://www.youtube.com/watch?v=j-JPMgcyfvI
[4] Resample geometry node. (n.d.). sidefx.com. https://www.sidefx.com/docs/houdini/nodes/sop/resample.html
[5] Class. (n.d.). Epic Dev. https://dev.epicgames.com/documentation/en-us/uefn/class-in-verse
[6] IdentityRotation function. (n.d.). Epic Dev. https://dev.epicgames.com/documentation/en-us/uefn/verse-api/unrealenginedotcom/temporary/spatialmath/identityrotation
[7] Specifiers and Attributes. (n.d.). Epic Dev. https://dev.epicgames.com/documentation/en-us/uefn/specifiers-and-attributes-in-verse#effect%20specifiers
[8] Instantiating a struct in Verse. (n.d.). Epic Dev. https://forums.unrealengine.com/t/instantiating-a-struct-in-verse/821142/2
[9] debug_draw class. (n.d.). Epic Dev. https://dev.epicgames.com/documentation/en-us/uefn/verse-api/unrealenginedotcom/temporary/diagnostics/debug_draw
[10] Lötwig Fusel. (2023, June 14). SwapChain | D3D12 Beginners Tutorial [D3D12EZ] [Video]. YouTube. https://www.youtube.com/watch?v=IE1wTLVpVRg