以下は、zipファイル内の三番目(index==2)のファイルを展開するプログラム。
#include <zip.h> #include <iostream> #pragma comment(lib,"zip.lib") int main(int argc, char* argv[]) { // ZIPファイルを読み取り専用で開く int errorp;
zip_t* zipper = zip_open(R"(C:\test\zipdata.zip)", ZIP_RDONLY , &errorp); // ZIP内のファイルの個数を取得 zip_int64_t num_entries = zip_get_num_entries(zipper, 0); // ZIP内のファイルの各ファイル名を取得 std::cout << "count: " << num_entries << std::endl; for (zip_int64_t index = 0; index < num_entries; index++) { std::cout << "[" << index << "]" << zip_get_name(zipper, index, ZIP_FL_ENC_RAW) << std::endl; } // ZIP内の2番目のファイルに関する情報を取得する struct zip_stat sb; zip_int64_t index = 2; zip_stat_index(zipper, index, 0, &sb); // 2番目のファイルのファイルサイズと同じメモリを確保する char* contents = new char[sb.size]; // 2番目のファイルの内容をメモリに読み込む zip_file* zf = zip_fopen(zipper, sb.name, 0); zip_fread(zf, contents, sb.size); zip_fclose(zf); zip_close(zipper);
////////////////// // ファイル名を出力できる形に変更 // ファイル一覧は階層構造をしておらず、ディレクトリ区切りは'/'で直接出力できないので // ファイル名中の'/'を'-'に置き換える。 // 本来なら再帰的にディレクトリを作るなどすべき。 std::string target = sb.name; for (size_t i = 0; i < target.size(); i++) { if (target[i] == '/') { target[i] = '-'; } } // //////////////////
// 解凍したファイルを作成 std::string outname = R"(C:\test\)" + target; FILE* of = fopen(outname.c_str(), "wb"); fwrite(contents, 1, sb.size, of); fclose(of);
int i; std::cin >> i; }
#include <zip.h> #pragma comment(lib,"zip.lib") int main(int argc, char* argv[]) { int errorp; zip_t* zipper = zip_open(R"(C:\dev\out.zip)", ZIP_CREATE | ZIP_EXCL, &errorp); zip_source_t* source; try { ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // ファイル追加 source = zip_source_file(zipper, R"(C:\test\data\img1.jpg)", 0, 0); if (zip_file_add(zipper, R"(img1.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } source = zip_source_file(zipper, R"(C:\test\data\img2.jpg)", 0, 0); if (zip_file_add(zipper, R"(img2.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } source = zip_source_file(zipper, R"(C:\test\data\img3.jpg)", 0, 0); if (zip_file_add(zipper, R"(img3.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // ディレクトリ追加 if (zip_dir_add(zipper, "folder", ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // ファイル追加 source = zip_source_file(zipper, R"(C:\test\data\dir\img4.jpg)", 0, 0); if (zip_file_add(zipper, R"(folder\img4.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } source = zip_source_file(zipper, R"(C:\test\data\dir\img5.jpg)", 0, 0); if (zip_file_add(zipper, R"(folder\img5.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } source = zip_source_file(zipper, R"(C:\test\data\dir\img6.jpg)", 0, 0); if (zip_file_add(zipper, R"(folder\img6.jpg)", source, ZIP_FL_ENC_UTF_8) < 0) { //エラー処理 zip_source_free(source); throw 1; } zip_close(zipper); } catch (...) { zip_close(zipper); } return 0; }
libzipのビルドにはzlibが必要。
libpngをやったときのzlibを使いまわすのでこの点は省略する。
まずConfigureすると、以下のようにエラーが出る。
とりあえずzlibのパスとインストール先を指定する。
この状態でConfigureすると、以下のようにBZIP2とLIBLZMAでWarningが出るが、support disabledと言われているだけなので無視してGenerateしてOpen Projectする。
Open ProjectしたらReleaseにしてALL BUILDしてINSTALLする。
そもそもなんでlibzipをやろうと思ったかというと、今まで勝手にzlibがzipファイル作成ライブラリだと思い込んでいて、libpng関連でzlibについて調べて初めて真相を知ったから。
あと、次回はサンプルコードを書く。
DAZ のシーンを Blenderに読み込むアドオン。
今回使用した環境
Blender 2.82 , DAZ 4.12
http://diffeomorphic.blogspot.com/p/daz-importer-version-14.html
私はモデリングやレンダリングに関してはライト層なのでcatとsheepがとりあえず出てくればいいや程度の判断しかしておらず、他のアドオンより優れていると判断して扱っているわけではないのでその点を踏まえてください。
インストールマニュアルがもの凄く親切に画像を載せて書かれているので殆どここを読めばできる。
http://diffeomorphic.blogspot.com/p/daz-importer-version-14.html
0.zipをダウンロード・展開
1.Blender 側のアドオンをインストール・設定
2.DAZ Studio 側のアドオンをインストール
3.DAZ library pathの設定(いらない)
4.DAZで普通に.dufファイルを保存,アドオンで同名の.jsonファイルを出力
5.Blender側で読込
ダウンロードリンクをクリックした先はDropboxなのでその辺にあるダウンロードボタンを押してダウンロードする。
インストールはマニュアルそのままでいい。
http://diffeomorphic.blogspot.com/p/installing-blender-add-on.html
要約:「Edit->Preferenceからadd-onsのInstallでダウンロードしたzipをそのまま指定してチェックもいれちゃってください」
設定もおそらくは基本そのままでいいはずだがエラーが出たら下参照。
Blender側の設定で最も重要なことは「DAZのフィギュアデータが入っているディレクトリを指定する事」で、使ってみてファイルが見つかりませんのようなエラーが出た場合まずここを疑うべき。
これも公式そのままでいい。
http://diffeomorphic.blogspot.com/p/installing-daz-studio-plugin.html
基本やらなくていい。
DAZで普通にフィギュアを設定し、
で.dufファイルを保存
今回新しく入れたアドオンで、dufファイルと同じ場所に.jsonファイルを出力する。ファイル名部分はdufファイルと同じである必要がある。
[File]→[Import]→[DAZ Native]
または、以下Import DAZ Fileからdufファイルを読み込む
ファイルが見つからないとエラーが出る場合がある。以下エラーログ:
私の場合、フィギュアのフォルダ構成が
のような状態になっていたからで、特に赤字部分はDAZコネクトによりインストールすることで勝手に決められてしまう。Daz Importer 1.4ではディレクトリが9個しか(?)登録できないこともあり、これを全部登録するのは無理がある。
\data\ 以下の青時部分は共通しているので、\cloud\(数字)\ より下の内容を全部他の場所に固めてコピーし、そのディレクトリを指定すれば動くようにはなる。
今後のことも考えればDAZコネクト使用時のディレクトリをわかりやすいものにする方法を探すべき。
だが見つからなかったので、DAZ Install Managerからインストールしなおした。
DAZ Install Manager からダウンロードした場合、格納先はBasic Settings...から確認できる。そして多分デフォルトでインストールしたならこのパスはBlenderのaddon側に既に入っていると思うので変える必要はない(かもしれないが確認したほうがいい)
参考:(DAZ コネクトについて)
http://kotozone.blog55.fc2.com/blog-entry-392.html
公式の一番目立つダウンロードを押しても少なくともWindows版はよくわからないところに飛ばされるので以下からダウンロードする
https://graphviz.gitlab.io/_pages/Download/Download_windows.html
graph g{
node[
fontname="MS Gothic"
]
"いろは" -- "にほへと" -- "ちりぬるを";
}
日本語を表示する場合、fontnameに日本語フォントを指定する必要がある。
\release\bin\dot.exe をコマンドプロンプトから実行する
ここで赤字は出力形式。当然だが出力はカレントディレクトリなのでパスを通さず上記を実行するとdot.exeと同じ場所にa.pngが生成される。
出力形式一覧
https://graphviz.org/doc/info/output.html
graph g{
node[
fontname="MS Gothic"
]
"いろは" -- "にほへと" -- "ちりぬるを";
}
矢印には digraphを使う
digraph g{
node[
fontname="MS Gothic"
]
"いろは" -> "にほへと" -> "ちりぬるを";
"いろは" -> "日本語";
"日本語" -> "いろは";
}
digraph g{
node[
fontname="MS Gothic"
]
//ノード定義
"いろは" [fillcolor=plum ,style=filled]
"にほへと" [fillcolor=cyan ,style=filled]
"ちりぬるを" [fillcolor=white,style=filled]
"いろは" -> "にほへと";
"いろは" -> "ちりぬるを";
}
色一覧
http://www.graphviz.org/doc/info/colors.html
digraph g{
node[ fontname="MS Gothic" ]
edge[ fontname="MS Gothic" ]
"いろは" -> "にほへと" [label="連続"];
"いろは" -> "ちりぬるを" [label="非連続"];
}
digraph g{
node[ fontname="MS Gothic" ]
//ノードの定義
"いろは" [shape=circle];
"にほへと" [shape=triangle];
"ちりぬるを" [shape=diamond]
"いろは" -> "にほへと";
"いろは" -> "ちりぬるを";
}
ノードの形状一覧:
https://graphviz.gitlab.io/_pages/doc/info/shapes.html
import bpy
# textオブジェクトの追加
fontCurve1 = bpy.data.curves.new(type="FONT",name="fontCurve1") obj = bpy.data.objects.new("textObject",fontCurve1) obj.data.body = "Hello"# textオブジェクトの内容 # 新しいCollrectionを作成 newCol = bpy.data.collections.new('Collection 1') # 現在のシーンにコレクションをリンク bpy.context.scene.collection.children.link(newCol) newCol.objects.link(obj)
# フォントの変更
fnt = bpy.data.fonts.load('C:\Windows\Fonts\HARNGTON.TTF') obj.data.font = fnt
すっかり忘れていたが今までのパターンではdouble型にしか対応していなかった。
#pragma once ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // プライマリテンプレート template<typename T> struct GETTER; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化用の構造体 //小文字 x,y,z用特殊化用の構造体 template<typename T> struct access_xyz { using scalar_t = decltype(T::x); static inline scalar_t& X(T& v) { return v.x; } static inline scalar_t& Y(T& v) { return v.y; } static inline scalar_t& Z(T& v) { return v.z; } static inline const scalar_t& X(const T& v) { return v.x; } static inline const scalar_t& Y(const T& v) { return v.y; } static inline const scalar_t& Z(const T& v) { return v.z; } }; //大文字 X,Y,Z用特殊化用の構造体 template<typename T> struct access_XYZ { using scalar_t = decltype(T::X); static inline scalar_t& X(T& v) { return v.X; } static inline scalar_t& Y(T& v) { return v.Y; } static inline scalar_t& Z(T& v) { return v.Z; } static inline const scalar_t& X(const T& v) { return v.X; } static inline const scalar_t& Y(const T& v) { return v.Y; } static inline const scalar_t& Z(const T& v) { return v.Z; } }; //配列用特殊化用の構造体 template<typename U,typename T> struct access_ARRAY{ static inline U& X(T& v) { return v[0]; } static inline U& Y(T& v) { return v[1]; } static inline U& Z(T& v) { return v[2]; } static inline const U& X(const T& v) { return v[0]; } static inline const U& Y(const T& v) { return v[1]; } static inline const U& Z(const T& v) { return v[2]; } }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // データ型(サンプル) // 型1 struct vec_t { double x, y, z; }; // 型2 struct VEC_t { double X, Y, Z; }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// //特殊化1(デフォルトの型) template<> struct GETTER<vec_t> :public access_xyz<vec_t> {}; template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化2(ポインタ版) template<typename T> struct GETTER<T*> : public access_ARRAY<T,T*> {}; template<class T, std::size_t N> struct GETTER<T[N]> : public access_ARRAY<T, T[N]> {}; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > : public access_ARRAY<T, std::array<T, N> > {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); } template< typename T, class G = GETTER<T> > void normalize(T & v) { double L = length(v); G::X(v) = G::X(v) / L; G::Y(v) = G::Y(v) / L; G::Z(v) = G::Z(v) / L; }
前回、配列版の事を忘れていたので追加。
#pragma once ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // プライマリテンプレート template<typename T> struct GETTER; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化用の構造体//小文字 x,y,z用特殊化用の構造体 template<typename T> struct access_xyz { static inline double& X(T& v) { return v.x; } static inline double& Y(T& v) { return v.y; } static inline double& Z(T& v) { return v.z; } static inline const double& X(const T& v) { return v.x; } static inline const double& Y(const T& v) { return v.y; } static inline const double& Z(const T& v) { return v.z; } }; //大文字 X,Y,Z用特殊化用の構造体 template<typename T> struct access_XYZ { static inline double& X(T& v) { return v.X; } static inline double& Y(T& v) { return v.Y; } static inline double& Z(T& v) { return v.Z; } static inline const double& X(const T& v) { return v.X; } static inline const double& Y(const T& v) { return v.Y; } static inline const double& Z(const T& v) { return v.Z; } }; //配列用特殊化用の構造体 template<typename T> struct access_ARRAY{ static inline double& X(T& v) { return v[0]; } static inline double& Y(T& v) { return v[1]; } static inline double& Z(T& v) { return v[2]; } static inline const double& X(const T& v) { return v[0]; } static inline const double& Y(const T& v) { return v[1]; } static inline const double& Z(const T& v) { return v[2]; } };////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // データ型(サンプル)
// 型1 struct vec_t { double x, y, z; }; // 型2 struct VEC_t { double X, Y, Z; };
////////////////////////////////////////////////////// ////////////////////////////////////////////////////// //特殊化1(デフォルトの型) template<> struct GETTER<vec_t> :public access_xyz<vec_t> {}; template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 特殊化2(ポインタ版) template<typename T> struct GETTER<T*> : public access_ARRAY<T*> {}; template<class T, std::size_t N> struct GETTER<T[N]> : public access_ARRAY<T[N]> {}; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > : public access_ARRAY< std::array<T, N> > {};////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); } template< typename T, class G = GETTER<T> > void normalize(T & v) { double L = length(v); G::X(v) = G::X(v) / L; G::Y(v) = G::Y(v) / L; G::Z(v) = G::Z(v) / L; }
#include <iostream> #include <array> #include "len.hpp" ////エントリポイント int main() { double L; vec_t vv={ 1,1,1 }; L = length(vv); std::cout << L << std::endl; double xyz[3] = { 1,1,1 }; L = length(xyz); std::cout << L << std::endl; double* ptr = new double[3]{ 1,1,1 }; L = length(ptr); std::cout << L << std::endl; std::array<double, 3> ary = { 1,1,1 }; L = length(ary); std::cout << L << std::endl; int i; std::cin >> i; }
続き
せっかくテンプレートを使用しているのに、GETTERの特殊化が長すぎる問題がある。
今回はlength関数しか使用していないので特にそう感じる。x,y,zの要素をとる関数が、例えばinnner,outer,distance...等沢山あれば気にならない。
とはいえ、短いほうがいいのは間違いないので、できる限り少ない行数で特殊化できないか考える。
あらかじめ、要素がx,y,zの時に使えるaccess_xyzと、X,Y,Zの時に使えるaccess_XYZを用意しておく。
#pragma once ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // プライマリテンプレート template<typename T> struct GETTER;
////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // テンプレート
template<typename T> struct access_xyz { using arg_t = T; using carg_t = const T; static inline double& X(arg_t& v) { return v.x; } static inline double& Y(arg_t& v) { return v.y; } static inline double& Z(arg_t& v) { return v.z; } static inline const double& X(carg_t& v) { return v.x; } static inline const double& Y(carg_t& v) { return v.y; } static inline const double& Z(carg_t& v) { return v.z; } };template<typename T> struct access_XYZ { using arg_t = T; using carg_t = const T; static inline double& X(arg_t& v) { return v.X; } static inline double& Y(arg_t& v) { return v.Y; } static inline double& Z(arg_t& v) { return v.Z; } static inline const double& X(carg_t& v) { return v.X; } static inline const double& Y(carg_t& v) { return v.Y; } static inline const double& Z(carg_t& v) { return v.Z; } };////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // ポインタ版 (変更なし) template<typename T> struct GETTER<T*> { using arg_t = T *; using carg_t = const T*; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; template<class T, std::size_t N> struct GETTER<T[N]> { using arg_t = T[N]; using carg_t = const T[N]; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; template<typename T, std::size_t N> struct GETTER<std::array<T, N> > { using arg_t = std::array<T, N> &; using carg_t = const std::array<T, N> &; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } }; ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// // 関数本体 template< typename T, class G = GETTER<T> > double length(const T & v) { return sqrt( G::X(v) * G::X(v) + G::Y(v) * G::Y(v) + G::Z(v) * G::Z(v) ); }
使用したい構造体に合わせて、継承元を変える。
#include <array> #include "len.hpp" ////////////////////////////////////////////////////// // 型1 struct vec_t { double x, y, z; }; ////////////////////////////////////////////////////// // 型2 struct VEC_t { double X, Y, Z; }; //特殊化1 template<> struct GETTER<vec_t> :public access_xyz<vec_t> {};
//特殊化2 template<> struct GETTER<VEC_t> :public access_XYZ<VEC_t> {}; //エントリポイント int main() { double L; vec_t vv; vv.x = 1; vv.y = 1; vv.z = 1; L = length(vv); std::cout << L << std::endl; VEC_t VV; VV.X = 1; VV.Y = 1; VV.Z = 1; L = length(VV); std::cout << L << std::endl; int i; std::cin >> i; }
前回の続き
構造体が渡されたときとは別に、ポインタや配列が渡されたときも特殊化する必要がある。
プライマリテンプレートが以下の時、
//プライマリテンプレート template<typename T> struct GETTER;
ポインタ、配列、std::arrayで別の特殊化が必要
相手がポインタの場合、それを配列とみなすとする。
特殊化は以下のようになる。
template<typename T> struct GETTER<T*> { // ... };
相手が配列の場合、ポインタとは別の特殊化が必要になる
template<class T, std::size_t N> struct GETTER<T[N]> { // ... };
相手がstd::arrayの場合の特殊化は以下
template<typename T, std::size_t N> struct GETTER<std::array<T, N> > { // ... };
#include <type_traits> #include <array> #include "len.hpp"template<typename T> struct GETTER<T*> { using arg_t = T*; using carg_t = const T*; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };template<class T, std::size_t N> struct GETTER<T[N]> { using arg_t = T[N]; using carg_t = const T[N]; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };template<typename T, std::size_t N> struct GETTER<std::array<T, N> > { using arg_t = std::array<T, N> &; using carg_t = const std::array<T, N> &; static inline double& X(arg_t v) { return v[0]; } static inline double& Y(arg_t v) { return v[1]; } static inline double& Z(arg_t v) { return v[2]; } static inline const double& X(carg_t v) { return v[0]; } static inline const double& Y(carg_t v) { return v[1]; } static inline const double& Z(carg_t v) { return v[2]; } };//エントリポイント int main() { double L; vec_t vv; vv.x = 1; vv.y = 1; vv.z = 1; L = length(vv); std::cout << L << std::endl;//配列 double xyz[3]; xyz[0] = 1; xyz[1] = 1; xyz[2] = 1; L = length(xyz); std::cout << L << std::endl;//ポインタ double *pxyz = new double[3]; pxyz[0] = 1; pxyz[1] = 1; pxyz[2] = 1; L = length(pxyz); std::cout << L << std::endl;//std::array std::array<double, 3> ary; ary[0] = 1; ary[1] = 1; ary[2] = 1; L = length(ary); std::cout << L << std::endl;int i; std::cin >> i; }