とやったときと、
では、どう違うのかという話です。
例えば、このようなプログラムを書きます。
int main() { { FILE* fp = fopen("output-char-abc", "wb"); char* s = "abc"; fwrite(s, 1, 3, fp); // 3 byte 出力 fclose(fp);} { FILE* fp = fopen("output-char-あいう", "wb"); char* s = "あいう"; fwrite(s, 1, 6, fp); // 6 byte 出力 fclose(fp);
} { FILE* fp = fopen("output-wchar-abc", "wb"); wchar_t* s = L"abc"; fwrite(s, 1, 6, fp); // 6 byte 出力 fclose(fp);
} { FILE* fp = fopen("output-wchar-あいう", "wb"); wchar_t* s = L"あいう"; fwrite(s, 1, 6, fp); // 6 byte 出力 fclose(fp);
} return 0; }
このように、sの指す文字列の中身は、
LがついているときはUTF16、
ついていないときはShiftJIS
になります。
次に、プロジェクト設定の「文字コード」を、マルチバイト文字セットとUnicode文字セットでそれぞれ保存してみます。
この場合も、当然ですが、""とL""の結果も変わりません。上記したプログラムの挙動は、「文字セット」に関わらず同じです。
つぎに、プログラムの先頭にコメントで何らかの日本語を書いてみます。
結果はこのように、どちらの設定でもUTF16になります。
文字セットの設定はソースファイルの文字コードに影響を与えません。
ちなみにソースコードの文字コードを変えるには
等の方法があるようです。
では「文字セット」は、Visual Studioの何に影響を与えるのでしょうか。
このように、「文字セット」の設定によって、マクロ
・_UNICODE
・UNICODE
または
・_MBCS
が 定義されます。
つまり、「文字セット」の指定は
_UNICODEマクロが定義されるかどうか
の指定という意味です。
(続く...)
ターゲットの頂点の周囲の面にアクセスする。
http://vcg.isti.cnr.it/vcglib/adjacency.html
void OneRingNeighborhoodVF( MyVertex * v) { vcg::face::VFIterator<MyFace> vfi(v); //initialize the iterator tohe first face for(;!vfi.End();++vfi) { MyFace* f = vfi.F(); // ...do something with face f } }

これを応用して、ある頂点の周囲のエッジを選択する。
void OneRingNeighborhoodVE(MyVertex * v) { vcg::edge::VEIterator<MyEdge> vfe(v); for (; !vfe.End(); ++vfe) { MyEdge* e = vfe.E(); // ...do something with edge e } }

VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
Win32APIのWM_SIZEメッセージとWM_SIZINGメッセージ。
WM_SIZINGはサイズ変更中に、WM_SIZEはサイズ変更後に送られます・・・。
とはいうものの、発行されるタイミングより遙かに大きな違いがあります。というか全く別物です。
| lParam & 0xFFFF | クライアント領域の幅 |
| (lParam >> 16) & 0xFFFF | クライアント領域の高さ |
RECT rect;
GetClientRect(hWnd,&rect);
RECT* prect = (RECT*)lParam;
| prect->left | ウィンドウの左の座標 |
| prect->top | ウィンドウの上の座標 |
| prect->right | ウィンドウの右の座標 |
| prect->bottom | ウィンドウの下の座標 |
RECT rect;
GetWindowRect(hWnd,&rect);
case WM_SIZE: { printf(" WM_SIZE\n" "x-size : %d\n" "y-size : %d\n", lParam & 0xFFFF, (lParam >> 16) & 0xFFFF ); RECT rect; GetClientRect(hWnd, &rect); printf(" GetClientRect\n" "x-size : %d\n" "y-size : %d\n", rect.right, rect.bottom ); } puts("-----------"); break; case WM_SIZING: { RECT* prect = (RECT*)lParam; printf( " WM_SIZING\n" "left : %d\n" "top : %d\n" "right : %d\n" "bottom: %d\n" , prect->left, prect->top, prect->right, prect->bottom ); RECT rect; GetWindowRect(hWnd, &rect); printf( " GetWindowRect\n" "left : %d\n" "top : %d\n" "right : %d\n" "bottom: %d\n" , rect.left, rect.top, rect.right, rect.bottom ); puts(""); } break;
VCG LibraryでMeshに三角形を登録する方法
//パターン1 メッシュに頂点を追加してから、その頂点を結んで三角形を作成 MyMesh::VertexIterator vit = vcg::tri::Allocator< MyMesh >::AddVertices(mesh, 3); vit[0].P() = vcg::Point3f(0, 0, 0); vit[1].P() = vcg::Point3f(1, 0, 0); vit[2].P() = vcg::Point3f(1, 1, 0); vcg::tri::Allocator< MyMesh >::AddFace(mesh, &vit[0], &vit[1], &vit[2]); //パターン2 三つの頂点の座標を指定して三角形を追加 MyMesh::FaceIterator fit = vcg::tri::Allocator< MyMesh >::AddFace( mesh, vcg::Point3f(0, 0, 0), vcg::Point3f(-1, 0, 0), vcg::Point3f(-1, -1, 0) ); //面の色をここで指定 fit->C().X() = 255; fit->C().Y() = 0; fit->C().Z() = 0;
VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
VCG Libraryでポリゴンファイルを保存する方法。
#include <wrap/io_trimesh/export_ply.h> #include <wrap/io_trimesh/export_obj.h> #include <wrap/io_trimesh/export_stl.h>
class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Color4b, vcg::vertex::Normal3f, vcg::vertex::Qualityf, vcg::vertex::BitFlags, vcg::vertex::Mark > { }; class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::Color4b, // FACECOLORを保存するならこれを指定しておく vcg::face::Normal3f, vcg::face::Mark, vcg::face::BitFlags > { }; class MyEdge : public vcg::Edge< MyUsedTypes, vcg::edge::VertexRef, vcg::edge::BitFlags > { }; class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace>, std::vector<MyEdge> > { };
//メッシュを保存する vcg::tri::io::PlyInfo pi; pi.mask = vcg::tri::io::Mask::IOM_FACECOLOR | //色情報の出力を指定 vcg::tri::io::Mask::IOM_VERTNORMAL; vcg::tri::io::ExporterPLY<MyMesh>::Save( mesh, "result.ply", true, pi ); vcg::tri::io::ExporterOBJ<MyMesh>::Save( mesh, "result.obj", vcg::tri::io::Mask::IOM_FACECOLOR //これを入れるとmtlファイルも出力される ); vcg::tri::io::ExporterSTL<MyMesh>::Save( mesh, "result.stl", true //バイナリ形式ならtrue );
VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
VCGで色のついたポリゴンを表示する方法。
今回はplyファイルを使用。
※あと書くのも恥ずかしいけれど上記3ファイルはパブリックドメイン扱いとします。
面に色情報を持つデータを使用する場合、MyFaceで色情報を持つことを定義する。
class MyFace; class MyVertex; class MyEdge; struct MyUsedTypes : public vcg::UsedTypes< /*省略*/> {}; class MyVertex : public vcg::Vertex< /*省略*/> {}; class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::Color4b, vcg::face::Normal3f, vcg::face::Mark, vcg::face::BitFlags > { }; class MyEdge : public vcg::Edge< /*省略*/> {}; class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace>, std::vector<MyEdge> > { };
vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, "napple_face_color_0.ply");
色情報は C().X() , C().Y() C().Z() にそれぞれR,G,Bが入っている。cCはconst用。
上でvcg::face::Color4bを指定したので、unsigned char型で入っている。従ってOpenGLのglColor3ubを使用する。
glBegin(GL_TRIANGLES); for (const auto& f : mesh.face) { glColor3ub(f.cC().X(), f.cC().Y(), f.cC().Z()); for (size_t i = 0; i < 3; i++) { glVertex3d(f.cV(i)->cP().X(), f.cV(i)->cP().Y(), f.cV(i)->cP().Z()); } } glEnd();
頂点に色情報がある場合、MyVertexにColor4bを指定する。
class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Color4b, vcg::vertex::Normal3f, vcg::vertex::Qualityf, vcg::vertex::BitFlags, vcg::vertex::Mark > { };
vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, "napple_vertex_color.ply");
色情報はvertexの中に入っています。それ以外は面の時と同じです。
glBegin(GL_TRIANGLES); for (const auto& f : mesh.face) { for (size_t i = 0; i < 3; i++) { const MyVertex* pV = f.cV(i); glColor3ub(pV->cC().X(), pV->cC().Y(), pV->cC().Z()); glVertex3d(pV->cP().X(), pV->cP().Y(), pV->cP().Z()); } } glEnd();
VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
VCG Libraryでは、FaceがVertexのIteratorを持っていて、FaceからVertexを参照できる。
他の参照が必要な場合、vcg::tri::UpdateTopologyでFace-Edge間のリンクなどを計算できるのだが、例外が出たり、それっぽい変数に何も入っていないなどの現象に遭遇することがある。
例1:
を実行すると、
などというメッセージと共に例外がthrowされ停止する
例2:
OpenEdgeを表示しようと、faceオブジェクトからエッジオブジェクトを取得するためFEpやcFEpを使おうと、以下のように書くと、
for (const auto& f : mesh.face) { for (size_t i = 0; i < 3; i++) { if (vcg::face::IsBorder(f, i)) { glVertex3d( f.cFEp(i)->cV(0)->P().X(), f.cFEp(i)->cV(0)->P().Y(), f.cFEp(i)->cV(0)->P().Z()); glVertex3d( f.cFEp(i)->cV(1)->P().X(), f.cFEp(i)->cV(1)->P().Y(), f.cFEp(i)->cV(1)->P().Z()); } } }
と言って落ちる。恐らくリンク情報が作成されていない。
VCGではポリゴンを扱うために
と、既存の型を継承したデータ型を使う。この時、vcg::Vertex、vcg::Face,vcg::Edgeに各データ型を関連付ける適切な型をテンプレートで与える必要がある。
vcg::tri::UpdateTopology< MyMesh >::FaceFaceを使いたい場合、MyFace定義時に、vcg::face::FFAdjを指定する。なおテンプレート引数の順序は気にしなくて良い。
class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::Normal3f, vcg::face::FFAdj, vcg::face::EFAdj, vcg::face::Mark, vcg::face::VFAdj, vcg::face::BitFlags > { };
| 使用したい関数 | 指定するテンプレート引数 |
| vcg::tri::UpdateTopology< MyMesh >::FaceFace | MyFaceにvcg::face::FFAdj |
| vcg::tri::UpdateTopology< MyMesh >::VertexFace |
MyVertexにvcg::vertex::VFAdj MyFaceにvcg::face::VFAdj |
| vcg::tri::UpdateTopology< MyMesh >::VertexEdge |
MyVertexにvcg::vertex::VEAdj MyEdgeにvcg::edge::VEAdj |
| vcg::tri::UpdateTopology< MyMesh >::EdgeEdge | MyEdgeにvcg::edge::EEAdj |
例えばcFEp()を使いたい場合、まずエッジ情報を作成するため
を実行する。しかしAllocateEdgeが中でFFpを要求するので、先んじて
を実行する。FaceFaceを実行するためにはMyFaceにvcg::face::FFAdjを指定しなければならないので追加する。
するとcFEpでabortするので、MyFaceにvcg::face::FEAdjを指定する。
ここまでで、cFEpを使うコードは、以下のようになる。
※ただし、cFEpに必要な物以外を外してある。
//データ型の定義 class MyFace; class MyVertex; class MyEdge; struct MyUsedTypes : public vcg::UsedTypes< vcg::Use<MyVertex>::AsVertexType, vcg::Use<MyFace>::AsFaceType, vcg::Use<MyEdge>::AsEdgeType> {}; class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f> { }; class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::FFAdj, vcg::face::FEAdj> { }; class MyEdge : public vcg::Edge< MyUsedTypes, vcg::edge::VertexRef> { }; class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace>, std::vector<MyEdge> > { };
//データの読み込み vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, fname); //必要に応じて vcg::tri::Clean< MyMesh >::RemoveDuplicateVertex(mesh); vcg::tri::Clean< MyMesh >::RemoveDuplicateEdge(mesh); vcg::tri::Clean< MyMesh >::RemoveDuplicateFace(mesh); //エッジ情報作成 vcg::tri::UpdateTopology< MyMesh >::FaceFace(mesh); vcg::tri::UpdateTopology< MyMesh >::AllocateEdge(mesh);
表示
glLineWidth(2); glColor3d(0, 0, 1); glBegin(GL_LINES); for (const auto& f : mesh.face) { for (size_t i = 0; i < 3; i++) { glVertex3d( f.cFEp(i)->cV(0)->P().X(), f.cFEp(i)->cV(0)->P().Y(), f.cFEp(i)->cV(0)->P().Z()); glVertex3d( f.cFEp(i)->cV(1)->P().X(), f.cFEp(i)->cV(1)->P().Y(), f.cFEp(i)->cV(1)->P().Z()); } } glEnd();
VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
以下の、Clone or downloadからVCG Libraryをダウンロードする。
https://github.com/cnr-isti-vclab/vcglib/
//基本的なデータタイプ #include <vcg/complex/complex.h> // PLYファイルの入出力 #include <wrap/io_trimesh/import_ply.h> #include <wrap/io_trimesh/export_ply.h>
vcg::Vertex,vcg::Faceなどの既存型があるが、それらを継承した型を使うのが方針らしい。
class MyFace; class MyVertex; class MyEdge; struct MyUsedTypes : public vcg::UsedTypes< vcg::Use<MyVertex>::AsVertexType, vcg::Use<MyFace>::AsFaceType, vcg::Use<MyEdge>::AsEdgeType> {}; //頂点型 class MyVertex : public vcg::Vertex< MyUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Color4b, vcg::vertex::Normal3f, vcg::vertex::VFAdj, vcg::vertex::VEAdj, vcg::vertex::Qualityf, vcg::vertex::BitFlags, vcg::vertex::Mark> { //ここにメンバ変数を追加できる }; //面型 class MyFace : public vcg::Face < MyUsedTypes, vcg::face::VertexRef, vcg::face::Normal3f, vcg::face::FFAdj, vcg::face::EFAdj, vcg::face::Mark, vcg::face::VFAdj, vcg::face::BitFlags > { }; //エッジ型 class MyEdge : public vcg::Edge< MyUsedTypes, vcg::edge::VertexRef, vcg::edge::BitFlags, vcg::edge::EVAdj, vcg::edge::EFAdj> { }; //3Dモデル型 class MyMesh : public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace>, std::vector<MyEdge> > { };
エッジ情報などはデフォルトでは計算してくれないので、UpdateTopologyのAllocateEdgeなどで作成する
//メッシュデータオブジェクト MyMesh mesh; int main(int argc, char **argv) { //plyファイル読み込み vcg::tri::io::ImporterPLY<MyMesh>::Open(mesh, "data.ply"); //面法線計算 vcg::tri::UpdateNormal<MyMesh>::PerFace(mesh); //Triangleのエッジ情報を作成 vcg::tri::UpdateTopology<MyMesh>::AllocateEdge(mesh); //縮尺 // meshオブジェクトがbboxメンバ(Bounding Box)を持っているので、 // モデルの最大・最小の座標がわかる double scalex = 1.0 / (mesh.bbox.max.X() - mesh.bbox.min.X()); double scaley = 1.0 / (mesh.bbox.max.Y() - mesh.bbox.min.Y()); double scalez = 1.0 / (mesh.bbox.max.Z() - mesh.bbox.min.Z()); double scale = (std::min)((std::min)(scalex, scaley), scalez); //センタリング double offsx = mesh.bbox.min.X() + (mesh.bbox.max.X() - mesh.bbox.min.X()) / 2; double offsy = mesh.bbox.min.Y() + (mesh.bbox.max.Y() - mesh.bbox.min.Y()) / 2; double offsz = mesh.bbox.min.Z() + (mesh.bbox.max.Z() - mesh.bbox.min.Z()) / 2;
全ての三角形はmeshオブジェクト内のface配列に格納されている。
//三角形で表示 void disp_triangles() { //マテリアルの設定 glMaterialfv(GL_FRONT, GL_AMBIENT, material_ambient); glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse_w); //描画処理本体 // mesh.face[0].N で面法線 // mesh.face[0].V(0)->C.X() で三角形の第一頂点のR // mesh.face[0].V(0)->P().X() で三角形の第一頂点のx座標 // * cがついているのはconstの意味 glBegin(GL_TRIANGLES); for (const auto& f : mesh.face) { glNormal3d(f.cN().X(), f.cN().Y(), f.cN().Z()); for (size_t i = 0; i < 3; i++) { glColor3ub(f.cV(i)->cC().X(), f.cV(i)->cC().Y(), f.cV(i)->cC().Z()); glVertex3d(f.cV(i)->cP().X(), f.cV(i)->cP().Y(), f.cV(i)->cP().Z()); } } glEnd(); } //三角形のエッジを表示 void disp_edge() { glDisable(GL_LIGHTING); glColor3d(1, 0, 0); glBegin(GL_LINES); for (const auto& e : mesh.edge) { glVertex3d(e.cV(0)->cP().X(), e.cV(0)->cP().Y(), e.cV(0)->cP().Z()); glVertex3d(e.cV(1)->cP().X(), e.cV(1)->cP().Y(), e.cV(1)->cP().Z()); } glEnd(); }
VCG LibraryのBall Pivotingでメッシュ生成
VCG Library ターゲットの周辺のオブジェクトを取得
Vray for Blender、Sun(Direct)のDecayの変化を一括して動画にしました。
Decayは減衰を表します。ライトの距離を離していくと、以下のように違いが現れます。
Point Cloud Library (PCL) と言うのを使っているのですが、その中でstlの入出力をしたくなりました。
#include <pcl/io/vtk_lib_io.h>
をしてから
pcl::io::loadPolygonFileSTL ()
を使ってみましたが、リンクエラーでvtkDebugLeaksManagerが見つからないといわれます。
答えを言うとvtkCommonCore-8.0.lib をリンクすればいいのですが、調べてみてもCMakeすればいいよみたいな情報しかなくて結構困りました。
vtkとついているんだからvtkのlibディレクトリを探せばいいことまではわかっています。ある程度目星がついているのに他を探し回るのは嫌だし、だからと言って200個あるlibを一つ一つリンクしてみるのも自分がかわいそうになるので、もう少しましな方法を考えます。
以下のようなBATファイルを作成しました(linksearch.bat)
使い方は、第一引数にライブラリディレクトリのパス、第二引数に検索したいシンボルを指定します。
linksearch "C:\Program Files\PCL 1.8.1\3rdParty\VTK\lib\*" vtkDebugLeaksManager@@QEAA@XZ
この出力結果(flistresult.txt)は、このようになります。
... (以下略)
※行が長くなるので中身を.\libx\に移しています
検索対象のvtkDebugLeaksManagerが表れているなら、その上のlib名で定義されています
本当は、必要なファイルだけを表示するなどしたかったのですが、Windowsのbatがよくわからずに断念しました。
Microsoft COFF Binary File Dumper (DUMPBIN.EXE) は、COFF (Common Object File Format) 形式のバイナリ ファイルに関する情報を出力します。 DUMPBIN を使うと、COFF オブジェクト ファイル、COFF オブジェクトの標準ライブラリ、実行可能ファイル、およびダイナミック リンク ライブラリ (DLL) の内容を確認できます。
ということで、dumpbinはexe,dll,libの内容を確認するためのツールです。
dumpbinはVisual Studioに入っています。Visual Studioのコマンドプロンプト、例えば「VS 2017用 x64 Native Tools コマンドプロンプト」から起動します。
そして、/LINKERMEMBER オプションをつけます。
このオプションは、ライブラリで定義されているパブリック シンボルを出力します。
ただしこれだけだと、必要のない情報も全部出力されてしまいます。テキストエディタの検索機能を使ってもいいのですが、せっかくなのでfindstrへパイプします。
ファイルの中からテキスト文字列を検索する。検索対象のパス指定が無ければ、プロンプトで入力されたテキストまたは別のコマンドからパイプ処理で渡されたテキストを検索する。正規表現の使用ができる。
即ち、目星のついているライブラリに対して、以下のように実行して、標準出力があればよいという事になります。
注意として、findstrに渡すシンボル名は大抵の場合、(C++でコンパイルされているなら)C++の命名規則で渡した方が確実のようです。@@とかついたものです。これはリンクエラーに書いてあるものをそのままコピペすればよいという意味です。
あとはこの内容をbatで適切に変えていけば良いと言うことになります。
Windowsのbatは(本当に)よくわからないので、解説出来ません。