FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

リファクタリング実例 OpenSceneGraph TangentSpaceGenerator

普段コードのリファクタリングをすることが良くあって、いつか作業の例を紹介したいなと思っていたのですが、
中々業務用のコードを公開するわけには行きませんので機会が無かったのですが、最近オープンソースの
コードリーディングをすることがあって、そのときに行ったリファクタリングの例を紹介したいと思います。


対象のコード

https://github.com/openscenegraph/OpenSceneGraph/blob/OpenSceneGraph-3.6.0/src/osgUtil/TangentSpaceGenerator.cpp

e0eb4fb on 21 Nov 2017
のリビジョンのコードの一部をリファクタリングしていきます。

これは、OpenSceneGraphという3DCG用のライブラリのコードの一部で、3D形状の接方向を推定するコードになっています。

コードの詳細は省略しますが、概要としては、まずこのモジュールに3D形状の一部を構成刷る三角形が与えられます。
で、その三角形の各頂点に対して接方向、及び従法線の方向を推定する、という内容になっています。

各変数の詳細説明は省略しますが、大体下記の命名ルールとなっているようです

P : position
N : normal(法線)
T : tangent(接線)
B : Binormal(従法線)


問題箇所抜粋

完全なコピペではないのですが、初期状態で次のような状態になっています。




やけに面倒なコードになっていますので、順を追ってコードをスリムにしていきます。



手順

まずはじめに下記の変換をやっていきます。

  • 冗長なコードを変数に抽出
  • 不要な代入をインライン化
  • コードを関連する処理ごとにグルーピング


これらの編集を加えたコードが次になります。




この段階ではコード量は増えてしまっていますが、以降の手順でどんどん圧縮されていきます。

続いて、次のステップでは単純なコードの調整だけではなく、理論を若干考慮した変換を行っていきます。

  • vcx.x, vcy.x, vcz.xが同値なので、参照する変数をまとめる+if文も1つにまとめる。
  • normalizeは不要なので削除する。

それぞれ、根拠はベクトルの計算を考えればわかります。

で、それらの変換を行ったコードがこちら。




このような状態にすると明らかになるのですが、実は単なるベクトルで計算すれば良いところが、成分単位で記述されているところが多く見られますので、そのあたりの不要なコードを省略してやります。




コードがこの状態になると、実はT123、B123が不要であることがわかります。
それぞれ、一回0で初期化される→値を1回加算される→1回参照される
というだけの流れになるので、不要な加算、代入を省略することができます。

また、if文はガード節に変換してやります。




ここまで来ると、実は外積がほとんど働いていないことがわかりますので、すべてインライン展開してやります。




で、次が最後。

コードがこの状態になると、またここでも本来ベクトル単位での演算で良いところを、成分単位で計算してしまっていますので、
省略してやります。




で以上になります。

最初のコードと比較すると、元々57行あったのが、17行と3分の1以下まで圧縮出来ることがわかります。



スポンサーサイト

3D関係素材サイト



HDRLabs sIBL_Archive
無料で使えるHDRが公開されています。



CC0 Textures
テクスチャデータ。
非常に高品質なのにCC0で公開されています。



Library: Pixar One Twenty Eight
Pixarのテクスチャライブラリです。
ややリピート処理がうまく出来ていません。
大体大丈夫ではありますが、ズームインすると結構目立つずれがあります。



Resources.blogscopia.com
3Dモデルが公開されています。
blendファイルが豊富にあります。




Blender用SVG出力プラグイン


Blender_ExportPathToSVG
https://github.com/fkhideaki/Blender_ExportPathToSVG


Blender用のSVGエクスポートプラグインを作りました。

snap_3707_180416_000145.png

と、こんな感じで、シーン内のストロークをSVGでエクスポートすることが出来ます。

Blenderには標準で「Freestyle SVG Exporter」というSVGのエクスポーターがあるのですが、どうも色々使いづらいところがある
のでそのあたりを改善しています。

Freestyleのエクスポータとの具体的な違いは
・実寸で出力できる
・ストロークをオブジェクト単位でグループ化して出力
・FreestyleSVGExporterから出力したSVGがイラレでインポートできないようなので、普通にインポートできるような形で出力
という感じです。

paint.net を最新にインストールしたらえらいことになった

paint.net

paint.netは起動時に最新版チェック+更新インストールする機能があって、UIから言われるままに更新をするととんでもないことになってしまいました。

この記事を書いている時点での最新版は4.0.21なのですが、詳細不明ですが、4.0.20あたりから対応する.Net Frameworkのバージョンが4.7.1に変わるらしく、どうもそのあたりでインストーラの処理に問題があるようです。

まず状況説明

  • paint.netを普通に起動→更新インストールのダイアログが表示される
  • 更新インストールを指示
  • インストーラが開始され
    「paint.net本体と.NetFrameworkをインストールします」
    という旨のダイアログが表示されるのでそのまま進める。
  • しばらく待っていると、インストールに失敗した、とメッセージが出て終了

と、こういった流れになりました。

これが非常に厄介でして、どうも.NetFrameworkのインストールが完全な失敗ではなく不完全な状態で一部だけインストールされてしまうらしく、.Netを使う他のソフトが全然動かなくなってしまいました。

一番最初に気づいたのはVisualStudioで、開発作業をしているときにいきなりコンパイラが動かなくなってしまいました。
で、とりあえずVisualStudioを再起動してみようとすると、今度は起動させようとすると起動時点でエラーになってしまいます。

では、.Net4.7を自分でインストールしなおしてやれば良いのでは、と考えやってみたのですが、結論としては無理でした。

というのは、、、

.NET Framework 4.7のオフラインインストール失敗の解決とインストーラーを解凍するコマンド
こちらのブログによると、どうも.Net4.7は単体ではインストールできず、前提となるモジュールをまずインストールしなければならない、ということのようです。
しかもそれだけでなくインストール作業自体にも色々しなければならない、という面倒な手順が必要らしい。
仕方ないのでこの手順に従ってインストールをしようとしてみたのですが、なんと私のPCではそもそもこの追加のインストーラを起動しようとすると
「このインストーラはこのPCには適用できない」
という感じのメッセージが出て起動すら出来ない、という状況で結局インストールはできませんでした。

おそらくpaint.netのインストーラがそのあたりの制御を正しく出来ていないものと考えられます。

最終的には.Net4.7をアンインストールして他のソフトが正常に動作する状況に復旧しましたが、そのため、paint.netの最新版は結局起動できない状況に。
仕方ないのでダウングレードすることに。
paint.netのサイトには旧バージョンの公開サイトが無かったのですが、かろうじてファイル自体は旧バージョンのものがおかれているようで、URL手入力でファイルをダウンロードして、旧バージョンを何とかインストールすることができました。

最新版:
https://www.dotpdn.com/files/paint.net.4.0.21.install.zip
旧バージョン(.Net4.6対応の最新版):
https://www.dotpdn.com/files/paint.net.4.0.19.install.zip

OpenGLで指定ピクセルの3D座標値を取得する方法



こんな感じです。

やり方自体は大昔からある方法で、サンプルコードもたくさん同様のものがあるのですが、微妙な間違いが含まれているものがちらほら見られいます。

というのは、3DCG全般なのですが、上下方向がスクリーン座標とCGの座標で逆になっている関係でy座標値を上下逆にする必要があるのですが、ここが

(x, h - y)

となっていることが多いのですが、上下反転するのであれば、

(x, h - y - 1)

が正解

×(x, h - y)
○(x, h - y - 1)

冷静に考えればわかるのですが、たとえば画面の高さ方向のピクセル数が100の場合に、y座標値0のところを参照する場合
-1がなければ
100 - y = 100
100ピクセルなら画面の座標値は0~99なので、これでは範囲外を参照してしまいます。
カレンダー
07 | 2018/08 | 09
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 -
最新記事
カテゴリ
Qt (21)
SDL (2)
MFC (2)
検索フォーム
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
リンク(管理用)
FC2カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。