普通、光は水に入ると次第に減衰していく。だから極めて浅いところでは色がなく、浅いところでは明るい色になり、深いところでは暗い色になる。
ところがCyclesのGlassは光の減衰を再現してくれないらしい。だから薄く色を付けたGlassのオブジェクトを使うと沼みたいになる。
仕方がないのでVolumeを使用。表面には別に半透明なマテリアルを指定し、Voronoiで波を再現して貼り付けている。
C++のDLLの中に、関数ポインタを取る関数が外部に公開されている。
これをC#から使いたい。
どういうわけか、以下コードのCallFunctionに渡す関数ポインタの型をtypedefした関数ポインタ型(CallFP)にしたところランタイムエラーが起こる。
仕方がないので、void*で受け取って呼び出し直前にキャストするようにしたところうまくいった。今のところ、意味が分からない。
ちなみに、DLLDefs.hはDLL作成時に使用するヘッダで使っているもの。
dlltest.h
#include "DLLDefs.h" #include <cstdint> /////////////////////////////////// /// C++側 (ヘッダ) ///////////////// /////////////////////////////////// int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved); typedef void(WINAPI *CallFP)(std::int32_t a, std::int32_t b); __DLL_PORT void WINAPI CallFunction(void* p,std::int32_t in1,std::int32_t in2);
dlltest.cpp
#include <Windows.h> #include "dlltest.h" /////////////////////////////////// /// C++側 (cpp) ///////////////// /////////////////////////////////// int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: //初期処理 break; case DLL_PROCESS_DETACH: //終了処理 break; } return 1; // OK }; void WINAPI CallFunction(void* p, std::int32_t in1, std::int32_t in2) { CallFP cp = static_cast<CallFP>(p); (*cp)(in1, in2); }
using System; using System.Runtime.InteropServices;//Marshal用 /////////////////////////////////// /// C#側 (呼び出し)///////////////// /////////////////////////////////// namespace ConsoleApplication1 { //コールバック関数の型を宣言 [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void TypeOfCallBack_t(System.Int32 a, System.Int32 b); class Program { //DLLの中の関数を宣言 [DllImport("Project1.dll",EntryPoint = "CallFunction") ] public static extern void CallFunction(IntPtr callbk,Int32 in1,Int32 in2); //コールバック関数本体。この関数がDLL経由で呼び出される static public void CallBackMain(Int32 a, Int32 b) { Console.Write(a + b + "\n"); } static TypeOfCallBack_t delgobj; static GCHandle gch; //エントリポイント public static void Main(string[] args) { delgobj = CallBackMain; IntPtr ptr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( delgobj ); gch = GCHandle.Alloc(delgobj); //関数を呼び出す CallFunction( ptr ,10,15); Console.Read(); gch.Free(); } } }
DLLを扱う際にimport,exportを分けるファイル。
DLLを作るプロジェクトへ読み込んだ場合は、プロジェクトの設定などでDLL_EXPORT_DOを定義しておけば、関数宣言時に__DLL_PORTを付けると公開関数となる
DLLを使うプロジェクトへ読み込んだ場合は、libをリンクするだけで関数を使えるようになる。
#ifdef DLL_EXPORT_DO /* DLLを作る場合 */ #define __DLL_PORT extern "C" __declspec(dllexport) #else /* DLLを使う場合 */ #define __DLL_PORT extern "C" __declspec(dllimport) #endif
もうすぐ冬なので雪を作りたい。
だがなかなかわかりやすいCyclesのノード構成図が見当たらない。
この絵の床は
https://www.packtpub.com/books/content/creating-ice-and-snow-materials
のiceを途中までやったのだがテクスチャが必要と言われ断念。
ゆきだるまのほうは自前で何かしらやった結果。
てか、iceこれで十分じゃね?(ちょっと変えてある)
template<typename T> struct coord { T x; T y; T z; coord() {} coord(const T _x, const T _y, const T _z) { x = _x; y = _y; z = _z; } template<typename U> coord<T>& operator=(const coord<U>& src) { x = src.x; y = src.y; z = src.z; return *this; } };
このような構造体があったとして、こいつにoperatorを定義するときにいつも悩むのが戻り値の型である。
template<typename T, typename U> double operator-(const coord<T>& s, U v) { typedef decltype(s.x - v) Type; return coord< Type >( static_cast<Type>(s.x - v), static_cast<Type>(s.y - v), static_cast<Type>(s.z - v) ); }
このように型を決め打ちしてしまうと、TもUもintなのにdoubleが返ってくることになったり、long doubleが入ってきたりすると潰れてしまう。
BoostにはBOOST::TYPEOFなるものがあるらしいが、このためにBoostを使うのは論外だ。
Boostにあるということはメタメタすればいけるんだろうが、これもやりたくない。
ここで思い出したのだが、今は仕事でもVC++2015を使っている。こいつのC++11対応はMicrosoftにしては良い線行っている。
autoとdecltypeを使えば、以下のように書ける。
template<typename T, typename U> auto operator-(const coord<T>& s, U v) { typedef decltype(s.x - v) Type; return coord< Type >( static_cast<Type>( s.x-v ), static_cast<Type>( s.y-v ), static_cast<Type>( s.z-v ) ); }
やはり、ターゲットプラットフォームに問題がないなら、Visual C++のバージョンは2015以降を使うことを人類の義務にすべきだ。トランプよ法律作れ。
Blender/Cycles 練習 作品No.00002 秋の草原と紅葉
早くしないと冬になってしまうのでとりあえず秋っぽいものを作る。
といっても木はSapling、草はHair、背景はSky Textureなので何一つ自分で作ってない。
家電量販店(爆買いでも減益・赤字)
http://blog.livedoor.jp/nevada_report-investment/archives/4949260.html
家電量販店の業績が惨憺たる状況になっています。
中国人等の「爆買い」と言われる巨大需要を入れましても、業績悪化が進んでいるのです。コジマ 63億円の赤字(前期は10億円の黒字・予想は4.4億円の黒字) 無配転落へ
ビックカメラ 68億円の黒字(31%減益:予想は102億円)本来なら増額修正してもおかしくはない環境ですが、中国人の「爆買い」を入れても上記のような状況になっているのです。
これは日本人、特に地方での販売不振が深刻化しているからだと言え、このため家電量販店は都心に店舗を集中させてきていますが、中国人による「爆買い」が減少しつつあると言われており、家電量販店は更なる業績下方修正となるかも知れません。
リンクとはあまり関係ないのだが、地方の電気屋の品数の少なさはある意味仕方がないことではあるが、それを補う努力があまりされていない。
私がiPadを下見に行ったときの話。まず、iPadがネットにつながっていない。あんなネットありきの機械でネットにつながっていないなどふざけた話である。ダミーのウェブサイトすら用意していないので、Safariの使い勝手を確かめることすらできない。
あるいは、タッチペンの性能が売りのノートパソコンにも関わらず、付属しているClipStudioを起動できる電気屋を見たことがない。私自身はそんなに使うソフトではないのだが、ペン性能を確認したいときにPaintはないだろう。Fresh Paintは薄くて太い線しかかけないし(ちなみにこのあたりは新宿でも大差ない)
ネット通販がこれだけ普及している以上、電気屋は「来ていただく」立場に立たなければならないのではないか。こちらとしては、せっかく「行ってやって」も、広告の内容程度の事しかわからないのでは、利用価値がない。
じゃあどうすればいいかと言うと、私は、体験型のサービスを要求したい。行くことに意味を持たせなければならないからだ。実物を「見る」だけでも価値はあるが、通販でボタン一つで運んでくれる手軽さにそうそう勝てるものではない。
まず、あのうるさいBGMとテレビの垂れ流しをやめるか、スイッチ一つで切れるようにしておく。
その上で、例えば洗濯機を見に来た人には、実際に動かしてどの程度の音が出るか、振動はどうかを比較体験してもらう。オーディオ機器であれば静かな場所で聞くというのは特に重要なはずだ。勿論、自宅の個室と電気屋の開放的な空間では全く違うのだろうが、それはまあいい。
あるいは、マウス・キーボードコーナーにPCを置いておき、USBをさして試用できるといい。盗難防止措置はなんとかしろ。
既にそれが行われている分野もある。例えば蛍光灯だ。あれはつけておくだけだから簡単なのだろう。
だがパソコンはそれだけでは不十分だ。Windowsデスクトップが表示されているだけでは何の情報にもならない。Microsoftがいくらユーザーエクスペリエンス(利用者体験)を高らかに叫んでも、電気屋で体験させてもらえないのは片手落ちと言うものだ。
電気屋に行く、と言う行為そのもののせいで、交通費+時間だけでネット通販の割引率が吹き飛んでしまうという事だって珍しくない。それでも店舗に足を運ぶのは、パンフレットではどうにもわからないものを確認したいからに他ならない。
それとも、インター何とかって横文字はよくわからんですじゃという年寄りばかり相手にするつもりだろうか。あの方々がが新発売のスマホに行列を作る姿はなかなか想像が難しいのだが。
C/C++で警告レベルを高くしていると、意外なところで引っかかる。
自分で書いたモノならいくらでも直すのだが、他のライブラリや、IDEが勝手に作ったコードなんかの場合できる限り触りたくない。自分の管理下にないコードをいじると、アップデートが入ったとき修正箇所が多くなり大変である。
よく知られた方法として、
#pragma warning (disable : 4996 )
は特定の警告だけを無視できるが、そうではなく、特定の「箇所」だけに対してそれを行いたい。
触りたくないから触らないで居ると結局は直せない警告に埋もれて重要な警告を見落とす可能性が出てくる。
以下のコードは、VC++2012で/W4でコンパイルすると、
warning C4100: 'B' : 引数は関数の本体部で 1 度も参照されません。
だけが表示される。
#pragma warning(push) #pragma warning(disable:4100) void function_nouse_arg_A(int A){ printf("hello world!"); } #pragma warning(pop) void function_nouse_arg_B(int B){ printf("hello world!"); }
勿論普通はこんなことは行うべきではない。あくまで、警告に対応できない(すべきでない)合理的理由がある場合にだけ用いるべきだ。
鳩を飛ばせに行くんです、という曲があって、感覚が正常な人たちはみんな絶賛しているわけだが、私はどうしても納得できない。
http://www.utagoekissa.com/utagoe.php?title=hatowotobaseniyukundesu
考えてほしい。
靴が破れたらはきかえて
代わりがなければはだしでも
おなかがすいたらパンを食べ
なんにもなければがまんして
ぼくはずんずん行くんです
道をまっすぐどこまでも
嵐にあったらひなんして
熊にあったらうちとって
熊に会ったら避難してはいかんのか。
なぜ殺す。
じゃなくて、なんで鳩を飛ばすだけでこんな大冒険になるんだ?
鳩だってへんぴな山奥で放されても困るんじゃ無いか。そもそもどうやって連れて行くつもりだろう。
篭に入れてか?こんな大冒険を篭の中でじっと見ているのか?骨折るぞ。最悪死ぬぞ。
いやそれ以前に、なぜこの鳩は人間に飛ばされなければならなくなったのか。
怪我をして飛べなくなったのか?だったら拾ったところで放してやるべきだろう。もしやそんな山奥で拾ったのか?だとしたらこの冒険は二度目なんだが、それで歌にするほどの大冒険になるのか。
それとも人の元で育った鳩だろうか。だったら都会で放しても良さそうなものだが。というか山で生きていけないだろう。まさか獅子が子を千尋の谷に落とすがごとくのスパルタ教育か。なるほど学校で教わるわけだ。
考えられる最も納得のいくストーリーはこうだ。つまりこの鳩は異世界の生き物で、時空の裂け目的なところからこちらに迷い込んで蛇ににらまれた蛙のように困惑していたところを主人公が保護して、なんやかやで元の世界に帰るには○月×日の△山頂上に行かなければならないと言うことに・・・・
だめだ。鳩。自力でいけよ、飛べるんだから。
ちなみに、一つわかったことがある。子を谷に落とす獅子は中国の架空の生き物らしい。何にでも疑問を持てば、何かしら新たな知見が得られるということだろう。
アメリカ側の手続きが進んでいなくて先にアパートを追い出されたので☆の家に荷物共々転がり込んでいる。
☆もあまりいい顔をしていないが、震災に備えて貯めておいた無駄に高価な粉末青汁とか、真空パック玄米とか、比較的新しい洗濯機とかがただで手に入ったんでなんとか収まっている。賞味期限が切れていることはいわないでおいた方が良さそうである。
それはさておき、黒猫大和に問い合わせたら荷物30個をヤマト便で送ってくれるというので頼んだら、集配の人がものすごくいやな顔をしていた。というか梱包を自分でするなら引っ越し便使えないといったのはヤマト側なんだが、どうもそんなことはないらしい。受付と現場の認識の乖離が激しい。
さて、四月からの職場の上司との打ち合わせで、VC++2005を使っていることが発覚。でGDIで一生懸命図を書いていて、この人プログラマでもないのに凄いなと思ったんだが、アルファチャンネルをどんなに頑張っても加えられないと嘆いていたので、GDI+使うといいよと教えてあげたら喜んでた。
で、gdiplusを使うのはいいんだが、コントロール自作してたらDrawImageでちらつくことが発覚し、仕方が無いのでオフスクリーンレンダリングしてAlpaBlendしようと思った。
のだが、問題が発覚した。
OnPaintの中で以下のコードを走らせる。その際、OnSizingでInvalidateするようにして、マウスパッドを消しゴムで消すようにマウスで振り回しウィンドウサイズを変えていると、だいたい1~2分すると描画が一切されなくなる。
絶対メモリリーク的な何かがおこってると思ったが、案の定、それを指摘している人がいた。
CPaintDC dc(this); // 描画のデバイス コンテキスト RECT rect; rect.top = 20; rect.left = 40; rect.right = 200; rect.bottom = 200; Gdiplus::Bitmap backbuffer(rect.right, rect.bottom); CDC memDC; memDC.CreateCompatibleDC(&dc); HBITMAP hbmp; backbuffer.GetHBITMAP(Gdiplus::Color(0, 0, 0, 0), &hbmp); HBITMAP oldbmp = (HBITMAP)memDC.SelectObject(hbmp); Gdiplus::Graphics g(memDC); for (size_t i = 0; i < 10; i++) { Gdiplus::Rect rct(0, i * 50, 50, 50); Gdiplus::SolidBrush brush(Gdiplus::Color(100, 255, 0, 0)); g.FillRectangle(&brush, rct); } dc.BitBlt(0, 0, rect.right, rect.bottom, &memDC, 0, 0, SRCCOPY); memDC.SelectObject(oldbmp); //DeleteObject(hbmp); ① CDialogEx::OnPaint();
解決策は最後から三行目、①のコメントを外すこと。
というか
https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms536295%28v=vs.85%29.aspx
説明読むと、
The Bitmap::GetHBITMAP method creates a Windows Graphics Device Interface (GDI) bitmap from this Bitmap object.
つまりGDI bitmapを作るっていう関数なので、作ったら破棄しなければいけないのは当たり前だ。