1.UV展開する(テクスチャを使うため)
2.[Object] - [Object Tree] の「+」をクリックしてObject Node Treeを追加する
3.[V-Ray Object Node Tree] を表示する
4.[Geometry] - [Displacement]ノードを追加する
5.テクスチャのintensityをDisplacementのfloatへ接続する。
必要時応じて[Amount]を大きくする
6.レンダリング
7.色はマテリアル設定で[Displacement]と同じテクスチャを指定している
右クリックメニューと同じ要領で、ボタンを押した場所にメニューを出すことを考える。
#include <windows.h> #include <tchar.h> #include "resource.h" HMENU hmenu_dummy; const UINT ID_MENU_1 = 100; const UINT ID_MENU_2 = 101; INT_PTR CALLBACK DlgWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ INT_PTR ret = FALSE; switch (msg) { case WM_DESTROY: DestroyMenu(hmenu_dummy); break; case WM_INITDIALOG://メニューの初期設定/////////////////////////// hmenu_dummy = CreatePopupMenu(); //トップのダミーメニュー MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_TYPE; mii.fType = MFT_STRING; mii.wID = ID_MENU_1; mii.dwTypeData = _T("項目1"); InsertMenuItem(hmenu_dummy, ID_MENU_1, FALSE, &mii);//メニューに項目追加 mii.wID = ID_MENU_2; mii.dwTypeData = _T("項目2"); InsertMenuItem(hmenu_dummy, ID_MENU_2, FALSE, &mii);//メニューに項目追加 break; case WM_COMMAND: switch(wp){ case IDC_BUTTON_MENU://ボタンを押したとき////////////////////// { RECT brect;//ボタンの矩形を取得 GetWindowRect(GetDlgItem(hWnd, IDC_BUTTON_MENU),&brect); TrackPopupMenu(//メニューを表示 hmenu_dummy, TPM_LEFTALIGN, //↓に指定する座標はメニューの左上 brect.left,brect.top + (brect.bottom-brect.top), 0, hWnd,//親ウィンドウ nullptr ); break; } case ID_MENU_1://メニュー1が押された//////////////////////// MessageBox(hWnd,_T("メニュー1"),0,0); break; case ID_MENU_2://メニュー2が押された//////////////////////// MessageBox(hWnd,_T("メニュー2"),0,0); break; } break; // ダイアログを閉じる case WM_CLOSE: EndDialog( hWnd , (INT_PTR)WM_CLOSE ); ret =TRUE; break; } return ret; } /////////////////////////////////////////////// // エントリーポイント ////////////////////////// ////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow ) { INT_PTR d = DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),nullptr,(DLGPROC)DlgWndProc ); PostQuitMessage(0); return 0; }
C++CLIでのDictionaryの使い方 一般的なものまとめ
System::Collections::Generic::Dictionary<String^,int>^ dic = gcnew System::Collections::Generic::Dictionary<String^,int>();
dic->Add("零",0); dic->Add("一",1); dic->Add("二",2); dic->Add("三",3); dic->Add("四",4);
int ret; ret = dic["零"]; Console::Write( String::Format("零 : {0}\n",ret) ); //または dic->TryGetValue("一",ret); Console::Write( String::Format("一 : {0}\n",ret) );
if (dic->Remove("二") == true) { Console::WriteLine("成功"); } else { Console::WriteLine("失敗"); } if (dic->Remove("八") == true) { Console::WriteLine("成功"); } else { Console::WriteLine("失敗"); }
System::Collections::Generic::Dictionary<String^, int>^ dup = gcnew System::Collections::Generic::Dictionary<String^, int>(dic);
if (dic->ContainsKey("一")==true) { Console::WriteLine( dic["一"] ); } if (dic->ContainsValue(1) == true) { Console::WriteLine("1 は存在する"); }
for each( String^ key in dic->Keys ) { Console::Write( String::Format("{0}\n",key) ); }
for each( int value in dic->Values ) { Console::Write( String::Format("{0}\n",value) ); }
for each( System::Collections::Generic::KeyValuePair<String^,int> pair in dic) { Console::Write( String::Format("{0} {1}\n",pair.Key,pair.Value) ); }
以下の関数ChangeExtendは拡張子を変更する。
拡張子を変えたい事態と言うのは時折生じる。例えばfilename.txtという入力に対し、filname.backupというファイル名を出力したいとか、ファイル名がfilename.docでも、中身はプレーンテキストなので.txtのほうが都合がいいなどだ。
この関数はファイル名の拡張子部分のみを指定した文字列に置き換える。ただし拡張子がない場合は指定した拡張子を付け加える。
#include <cassert> #pragma warning( disable : 4996 ) //! @brief 入力したファイル名の拡張子を指定したものに変更する //! @param [in,out] fname 少なくともファイル名を含むファイルパス //! @param [in] ext 新しい拡張子。「.」を含んではならない //! @warning ディレクトリ区切りは'\'とする //! @return なし void ChangeExtend(TCHAR* fname,TCHAR *ext){ assert(fname != nullptr); assert(ext != nullptr); TCHAR* ldot=fname; //最後に出現したディレクトリ区切りを求める TCHAR* posdir = _tcsrchr(fname,_T('\\')); //最後に出現した.を求める ldot=_tcsrchr(fname,_T('.')); //C:\abc.def\\abc など、最後の.より\の方が後に来る場合、拡張子なしと判断する if( posdir > ldot){ ldot = nullptr; } if( ldot == nullptr){ _tcscat(fname,_T(".")); } else{ _tcscpy(ldot,_T(".\0")); } _tcscat(fname,ext); } //////////////////////////////////////////////////// // テスト int _tmain(int argc, _TCHAR* argv[]) { TCHAR fname[1024]; _tcscpy(fname,_T("C:\\hello\\dir\\filename.doc")); ChangeExtend(fname,_T("txt")); _tprintf(fname); puts(""); getchar(); return 0; }
入力 | 出力 |
C:\hello\folder\ile | C:\hello\folder\file.txt |
C:\hello\folder\file.doc | C:\hello\folder\file.txt |
C:\hello\folder\.doc | C:\hello\folder\.txt |
C:\hello\folder\ | C:\hello\folder\.txt |
C:\hello\fol.der\file.doc | C:\hello\fol.der\file.txt |
file.doc | file.txt |
メニュー関連の関数として、以下がある。
CreateMenu |
ウィンドウのタイトルバーの下に張り付く横長のメニューを作成するための関数。この関数で作成したメニューに対し、AppendMenuまたはInsertMenuItemで項目を追加する。 |
CreatePopupMenu |
ポップアップメニュー、つまり縦に開かれるメニューを作成する関数。 |
AppendMenu |
InsertMenuItemに取って代わられ、いまは互換性のために存在している。
|
InsertMenuItem | メニューに項目を追加するための関数 |
従って、メニュー作成の手順は、
HMENU hMenuTop = CreateMenu();
としてメニューを作成し、
InsertMenuItem(hMenuTop , ID_MENU_TOP_1, FALSE, &mii1);
InsertMenuItem(hMenuTop , ID_MENU_TOP_2, FALSE, &mii2);
のようにメニュー項目を追加することになる。
最後に
SetMenu(hWnd,hMenuTop);
として、ウィンドウにメニューを関連づける。
ここで、上記mii1はMENUITEMINFO型の構造体の変数であり、メニューのアイテム追加の時に、アイテムの性質を渡すための変数である。
MENUITEMINFOはわかりにくいので、まずここにまとめる。
下記MENUITEMINFOのメンバのうち、どれを使うかをfMaskで指定する。
MENUITEMINFO mii;
メンバ名 | 指定例 | fMaskの指定 | 説明 |
mii.cbSize | = sizeof(MENUITEMINFO); | - | MENUITEMINFOのサイズ |
mii.fMask | = MIIM_ID | MIIM_STRING; | - | 以下のパラメータのうち使用する物 |
mii.fType | = MFT_RADIOCHECK; | MIIM_FTYPE | アイテムのタイプ |
mii.fState | = MFS_ENABLED; | MIIM_STATE | アイテムの状態 |
mii.wID | = 100; //ユーザー定義 | MIIM_ID | アイテムID |
mii.hSubMenu | = hSubMenu;//ユーザー定義 | MIIM_SUBMENU | サブメニューのハンドル |
mii.hbmpChecked | = NULL; | MIIM_CHECKMARKS | チェック表示時のビットマップ |
mii.hbmpUnchecked | = NULL; | MIIM_CHECKMARKS | チェック非表示時のビットマップ |
mii.dwItemData | = 0;//ユーザー定義 | MIIM_DATA | 任意の32ビット値 |
mii.dwTypeData | = "ファイル(&F)"; | MIIM_STRING | アイテムの内容 |
mii.cch | = sizeof("ファイル(&F)" | - | アイテムの文字列の長さ |
mii.hbmpItem | = NULL; | MIIM_BITMAP | ビットマップハンドル |
例1 ポップアップメニューなし
//////////////////////////////////////////////// HMENU hmenu_top = CreateMenu(); // メニュー作成 const UINT ID_MENU_TOP_1 = 1; const UINT ID_MENU_TOP_2 = 2; //////////////////////////////////////////////// MENUITEMINFO mii; memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); //////////////////////////////////////////////// mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_TOP_1; mii.dwTypeData = _T("メニュー1"); InsertMenuItem(hmenu_top, ID_MENU_TOP_1, FALSE, &mii); mii.wID = ID_MENU_TOP_2; mii.dwTypeData = _T("メニュー2"); InsertMenuItem(hmenu_top, ID_MENU_TOP_2, FALSE, &mii); SetMenu(hDlg, hmenu_top);//ウィンドウにメニューを関連づける
例1 ポップアップメニューあり
//////////////////////////////////////////////// HMENU hmenu_top = CreateMenu(); // メニュー作成 const UINT ID_MENU_TOP_1 = 1; const UINT ID_MENU_TOP_2 = 2; HMENU hmenu_Lv1_1 = CreatePopupMenu(); //◆サブメニューの作成 HMENU hmenu_Lv1_2 = CreatePopupMenu(); //◆サブメニューの作成 //////////////////////////////////////////////// MENUITEMINFO mii; memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); //////////////////////////////////////////////// mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU ; mii.wID = ID_MENU_TOP_1; mii.hSubMenu = hmenu_Lv1_1; //◆サブメニューの追加 mii.dwTypeData = _T("メニュー1"); InsertMenuItem(hmenu_top, ID_MENU_TOP_1, FALSE, &mii); mii.wID = ID_MENU_TOP_2; mii.hSubMenu = hmenu_Lv1_2; //◆サブメニューの追加 mii.dwTypeData = _T("メニュー2"); InsertMenuItem(hmenu_top, ID_MENU_TOP_2, FALSE, &mii); SetMenu(hDlg, hmenu_top);//ウィンドウにメニューを関連づける //////////////////////////////////////////////// // ◆サブメニューの項目追加 const UINT ID_MENU_Lv1_1 = 3; const UINT ID_MENU_Lv1_2 = 4; const UINT ID_MENU_Lv1_3 = 5; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_Lv1_1; mii.dwTypeData = _T("サブ11"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_1, FALSE, &mii); mii.wID = ID_MENU_Lv1_2; mii.dwTypeData = _T("サブ12"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_2, FALSE, &mii); mii.wID = ID_MENU_Lv1_3; mii.dwTypeData = _T("サブ13"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_3, FALSE, &mii); //////////////////////////////////////////////// const UINT ID_MENU_Lv2_1 = 6; const UINT ID_MENU_Lv2_2 = 7; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_Lv2_1; mii.dwTypeData = _T("サブ21"); InsertMenuItem(hmenu_Lv1_2, ID_MENU_Lv2_1, FALSE, &mii); mii.wID = ID_MENU_Lv2_2; mii.dwTypeData = _T("サブ22"); InsertMenuItem(hmenu_Lv1_2, ID_MENU_Lv2_2, FALSE, &mii);
参考文献
http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_menu3.html
Vray for Blenderのテクスチャの中にFresnelが入っている。
http://tofusan.cocolog-nifty.com/blog/2013/03/post-557d.html
フレネル(Fresnel)とは、異なる屈折率を持つ2つの物体の界面において、光が反射する様子のこと
以下、Diffuseのカラーに繋いだ結果。平面だとわかりにくい。
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
球体だととてもわかりやすい。
![]() |
![]() |
![]() |
![]() |
C++のpimplとは何か。
pimplはコーディングテクニックのひとつで、ヘッダファイルから本来公開すべきではない項目を隠すことができるようになる。
#include "ClassTest.h" //エントリーポイント int _tmain(int argc, _TCHAR* argv[]) { CClassTest test; test.Set(100); test.Show(); getchar(); return 0; }
class CClassTest { private: class CClassTest_Impl* p_private;//CClassTestメンバはポインタのみ public: CClassTest(void); ~CClassTest(void); void Show()const; void Set(int val); };
#include "stdafx.h" #include "ClassTest.h" //公開したくない変数や関数をここに置く//////////////////// class CClassTest_Impl{ public: int m_value; }; //公開したいメンバ関数の実装///////////////////////////////////// CClassTest::CClassTest(void) { p_private = new CClassTest_Impl; } CClassTest::~CClassTest(void) { delete p_private; } void CClassTest::Show()const{ printf("%d\n",p_private->m_value); } void CClassTest::Set(int val){ p_private->m_value = val; }
①ヘッダファイルは普通cppファイルに#includeされる形で用いられる。
②#includeはファイルの内容をコピーするプリプロセッサである。
③つまり、CClassTest_ImplクラスをClassTest.hに書いても、ClassTest.cppに書いても、コンパイルの段階では全てClassTest.cppに書いたことになる。
④ならば最初からClassTest.cppに書いてしまえば、CClassTest_Implはcppファイルの中だけで完結する
⑤勿論、CClassTest_Implが他のファイルからも参照されるクラスならヘッダファイルに書かなければならない。
⑥しかし、CClassTest_ImplはCClassTestからしか用いない。従ってヘッダファイルで宣言を公開しておく必要がない。
⑦ClassTest.hではCClassTest_Implのポインタのみを宣言する。ポインタはsizeof(void*)長の変数であり、宣言時にクラスの内容がわからなくてもいい。
⑧こうして、ヘッダファイルから公開したくない項目をすべて隠すことが可能となる
中間管理職トネガワを見ているので久しぶりにカイジも見ているのだが、ついでに映画の実写版も見てみた。
感想を書くと批判の方が多くなってしまうのだが・・・今回に関してだけ言えば、そんなことは全く問題ではない。
なぜならカイジのスピンオフである「中間管理職トネガワ」がナレーション(を筆頭とした諸々のセンスのずれ)のせいでかなり悲惨な作品になってしまったからである。
多分この作品、ハガレンやヘルシングよろしく「中間管理職トネガワ Ultimate」とかで作り直してDVD化するんじゃないかな?←
というわけで実写版カイジの話。
カイジは自堕落なクズだが一方で他人の悪意に敏感な熱血漢でもある。そういうものを目の当たりにした時に彼が叫ぶさまはカイジらしかったと思う。
褒め言葉かと思いきやそうでもない。限定じゃんけん→地下生活(チンチロなし)→Eカードまでを二時間の中にぶち込んでいるのが原因だと思うのだが、確かによく言えば展開が速い。
一方で、一枚のカードを出すのに何分も悩んで堂々巡りしたり、どん底からのひらめきで必死に策を講じたり、そして策を実らせるために仲間と地べたに這いつくばるようにして努力する様は殆ど見られない。実際の所、原作は勝負の瞬間のために何時間も何日も準備する所が見所なので、その点が残念だ。本来カイジ視点で見れば、永遠のように感じる一瞬を固唾をのんで見つめ続けるようなシーンも多い。スピードは必要ないと思う。
利根川や会長は、殺虫剤をかけられた蛆虫がもがき苦しむのを眺めて笑うような感覚で債務者をいたぶるサイコパスである。
どうもこの利根川からはそういう、人を徹底的に見下した感性が伝わってこない。
会長にしても、次元が二けたくらい違うような圧倒的強者の落ち着きが感じられない。
遠藤さえ、鉄骨渡りを見ている投資家たちを見て不快感を示している。そんな感性が残っていてよく出世できたものだ。
やはり彼らには、クズが一周して悟りを開いたような違う世界の生き物であってほしい。
作品冒頭、シェルターを作るために労働者を集めよう、みたいなことを言っていたのだが、それなら劣悪債務者を片っ端からぶち込んでいけばいいだけで、わざわざ恩赦を与える必要はない。
エスポワールはあくまで会長達を楽しませることが主目的ではないだろうか。勿論、船の中で借金をしなければならないので、劣悪債務者昇格システムではあるのだが、強制労働や命がけのギャンブルなんて元々違法(違法と言えば金利がそもそも違法だし)なのだから、借金200万円以上は劣悪債務者ってことにしてしまえば済む話のように思う。
地下に落ちたらビールを奢ろう、という話。アニメ版では遠藤が「大人しく死ぬか、悪あがきして死ぬか」という究極の選択に迫られた時に、カイジから出された妥協案である。そこにはカイジという泥船に乗ってしまった後悔やら、それでも乗り続けるしかない絶望やら、要はドブネズミが逃げるために残しておいた後ろ足で猫に嚙みつくなんて正気の沙汰ではない心境だからこそ格好いいのだが、出世街道から外れただけの実写版遠藤がなぜカイジに乗ったのか・・・。
CreateDialog,DialogBox各関数でダイアログを作成した場合、配置したアイテムのウィンドウハンドルをどのように取得するのか。
これにはWin32APIのGetDlgItem関数を使う。
HWND hcontrol = GetDlgItem( ダイアログボックスのウィンドウハンドル , リソースのID(数値) )
#include <Windows.h> #include "resource.h" //IDD_DIALOG1の定義が入っている #include <tchar.h> //ダイアログプロシージャ INT_PTR CALLBACK DlgWndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { INT_PTR ret = FALSE; static HWND hbtn; switch (msg) { case WM_INITDIALOG: //初期化時にボタンの名称を変更する hbtn = GetDlgItem(hDlg, IDC_BUTTON1); SetWindowText(hbtn, _T("hello")); ret = TRUE; break; case WM_CLOSE: DestroyWindow(hDlg); PostQuitMessage(0); ret = TRUE; break; } return ret; } //エントリーポイント int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { //ダイアログを作成 HWND hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, (DLGPROC)DlgWndProc); ShowWindow(hDlg, SW_SHOW); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
次に、ハンドルはわかるがリソースIDがわからない場合。
これにはWin32APIのGetDlgCtrlID関数を使う。
int id = GetDlgCtrlID(ウィンドウハンドル)
#include <Windows.h> #include "resource.h" #include <tchar.h> #include <crtdbg.h> //ダイアログプロシージャ INT_PTR CALLBACK DlgWndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { INT_PTR ret = FALSE; HWND hscr; int id; switch (msg) { case WM_HSCROLL: hscr = (HWND)lp;//WM_HSCROLLのlParamにはハンドルが入っている id = GetDlgCtrlID(hscr);//動かしたスクロールバーのIDを取得 _RPT1(_CRT_WARN, "ID=%d\n", id); break; case WM_CLOSE: DestroyWindow(hDlg); PostQuitMessage(0); ret = TRUE; break; } return ret; } //エントリーポイント int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { //ダイアログを作成 HWND hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, (DLGPROC)DlgWndProc); ShowWindow(hDlg, SW_SHOW); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
CUDAでグラデーション画像を作成する。
勉強中なので突っ込みどころは多そうだが、気をつけたところは、
・1ブロック内のスレッド数を512以下にする
・1ブロック内のスレッド数を32の倍数にする(ワープの単位)
#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> #include <cstring> void pnmP3_Write(const char* const fname, const int vmax, const int width, const int height, const unsigned char* const p); /////////////////////////////////////////////// // GPU側 ////////////////////////////////////// __global__ void gradation(unsigned char* c,const int N) { //アクセス法 //このスレッドが担当する画素の位置を二次元座標で求める size_t xpos = blockIdx.x * blockDim.x + threadIdx.x; size_t ypos = blockIdx.y * blockDim.y + threadIdx.y; if (xpos < N && ypos < N) { size_t pos = N*ypos + xpos;//二次元座標を一次元座標に float R = ypos / (float)N; float G = (N - ypos) / (float)N; float B = xpos / (float)N; c[pos * 3 + 0] = R * 255;//0~255にして色書き込み c[pos * 3 + 1] = G * 255; c[pos * 3 + 2] = B * 255; } } ////////////////////////////////////////// //CPU側エントリーポイント/////////////////// int main(void) { //作成画像 N × N × 3 const int N = 1000; //16×16の領域に分けて計算する dim3 block(16, 16); //グリッド数 dim3 grid(N / 16+1, N / 16 + 1); unsigned char* p_gpu;//GPU側メモリ確保 cudaMalloc((void**)&p_gpu, N * N * 3); gradation << <grid, block >> > (p_gpu,N); //CPU側メモリ確保 unsigned char *p_cpu = new unsigned char[N * N * 3]; //GPU→CPU側へメモリコピー cudaMemcpy(p_cpu, p_gpu, N*N*3, cudaMemcpyDeviceToHost); cudaFree(p_gpu); //ファイル出力 pnmP3_Write("C:\\test\\hello.ppm", 255, N, N, p_cpu); delete[] p_cpu; getchar(); } ///////////////////////////////////////////// //画像ファイル書き出し///////////////////////// //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] vmax 全てのRGBの中の最大値 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void pnmP3_Write(const char* const fname, const int vmax, const int width, const int height, const unsigned char* const p) { // PPM ASCII FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, vmax); size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * 3 + 0], p[k * 3 + 1], p[k * 3 + 2]); k++; } fprintf(fp, "\n"); } fclose(fp); }