2014年12月13日土曜日
2014年10月4日土曜日
2014年9月22日月曜日
Pepper Tech Festival 2014 に行ってきた
先日Pepper Tech Festival 2014 に行ってきたので、メモを残しておきます。へっぽこ技術者なので偉そうなことは言えませんが、まことに僭越ながら個人の感想だけ…。
【概要】
■目的:Pepperの開発環境、開発舞台裏の公開、先行開発の展示等
■HP:http://www.pepper-techfes.jp/
■日時:2014/09/20 10:30~17:00(懇親会:17:30-19:00)
■場所:ベルサール渋谷ガーデン
■備考:
集客は1000人。抽選で選考。多分経歴や作品の項目は見られているかも。
SDKの配布あり(ハードウェア情報公開)。
先行予約抽選200名。当日1名抽選でお持ち帰り。
昼食、懇親会あり。おみやげあり。
【所感】
■総括
・大盛況であった。予約は初日ですでに500件。1台56万のロボットにこれほどの人が食いつくとは、とんでもないことである。とかくソフトバンクは話題性を作るのがうまい。タイミングといい、技術的なレベルといい。
・開発者フレンドリ感が半端ない。頭金20万+月1万×3年=計56万で手に入る。開発中壊れたら無償で修理。ペイするはずが無い。開発者思いの良心的な体制に涙ものでしょう。
http://www.softbank.jp/robot/special/tech/reserve/
・Web系、コンテンツ系の食いつきが大きく、雰囲気としては、スマホアプリが流行り始めたあたりに似ている。
・コテコテのロボットエンジニアや研究者は少数派。私のような田舎者には恐れ多い(?)空間だったが、逆を取ればチャンス。
・SDKはソフト屋としては至れり尽くせりな開発環境であった。
・先立って開発されたコンテンツのブースは未来を感じさせるものであった。スマホ感覚でアプリを入れられる世界も面白そうだけど、ガチなエンジニアや研究者介入すればもっと色々なことができるだろう。
・現状会話は作りこみのレベルで、感情の形成に直接結びつくような議論はまだ感じなかった。今後に期待。
■ハードウェア
・まじでハードは分からないが、技術的には従来レベルのものを精巧に組み合わせて製品化したのだと思う。マイク、タッチセンサ、カメラ、3Dセンサ、ジャイロセンサ…。どれを取っても新しいものではない。しかし、それがオールインワンになっていることに非常に価値がある。特にソフト屋に自分にとってはハードがこれほど揃っているなんて夢のようである。
・あれだけのセンサやアクチュエータを搭載したメカメカの塊を、コンシューマ向けの製品化までこぎつけたこと自体が、ソフトバンクの持つ総合力なのだろう。
■SDK
・Pepper自体の製品化はもちろん驚きだが、SDKの方が革命的だろう。従来、ロボットの開発環境というと、難解でクリエータさんが触れるレベルのものではなかったはずだ。その難しさはロボット開発者が補完していて、しかもその難しさを習得すること自体がロボット開発者のアイデンティティともなっていたように思う。
・そこを、ボックスと矢印をぺたぺたして、ちょっと動作を定義するだけの簡易なGUIで操作でき、かつ深いところはプログラミング言語で詳細に記述できるというのだから、クリエータ、エンジニア、研究者まで誰でも食いつける土台はできている。
・実はこのSDK、ソフトバンクがロボット事業で提携しているAldebaran Robotics社のChoregrapheというSDKを採用している。つまり、この洗練されたロボットSDKは既に存在していたわけで、これをAndroidSDKばりにオープン化すればビジネスになると睨んだソフトバンクはやはりすげー。来年くらいからこの手の本が売れるんだろうなー。
・自身を守るための基本動作が根底のレイヤで定義されている。衝突回避や転倒防止など。機能を実装する側がこれらを意識せずに開発に集中できる枠組みができている。なんだこれは。どんだけソフト屋に優しいんだ。
■サポート
・開発中の故障に関する修理は3年間無償らしい。月額の料金に組み込まれているよう。プレゼンで「ロボットは壊れるものです」と、家電とかパソコンでは考えられないようなフレーズを口にしたうえで、でもちゃんと面倒見ますよときて技術者を安心させるとは、うまいプレゼンです。
・技術サポートをするアトリエができるらしい。田舎ものの私には関係な(ry
・SDKのコミュニティがあるらしい。これは使えそう。
【展示スペース】
・IT関連分野に広く例題があったが、基本的には従来技術をPepperに適用・応用した事例である(技術なのか?といえるようなトンデモ展示もあったがw)。逆に言えば、既存技術を容易に適用しやすい開発環境が整備されているということである。その適用媒体がPepperになるだけで、未来を感じさせるような雰囲気をプンプンかもし出しているところに、彼らの存在意義がある。
■出展内容
・オープニングショー@HDMI(複数のPepperが踊ってた)
相互連携しているような感じがした。
・シンガー@YAMAHA(歌詞から曲生成 VOCALOID)
筐体がいるだけで楽しさ倍増な感じ。
・会話@1-10design(複数Pepeprと会話)
複数台いるとPepperの独特の世界感が出来上がって面白かった。
・家電制御@ユカイ(Pepperに家電制御を指示)
杖型の媒体をインタフェースとして家電を操作。未来感が出ていた。
・教育@Tryon(Pepperと一緒に遊びながら学ぶ)
教育用途は想定していた。語学とか。
・Webサービス@Yahoo(Pepper経由でYahooコンテンツ)
写真が無いorz... タブレットにYahooショッピングとかのアイコンがあった。
・データベース連携@IBM(IBM Watsonと連携して質問応答)
シークレットブースだったよう。当日公開された。人が写ってしまったので写真自粛。Pepperの筐体自体は今回はあまり関係ないけど。自然言語で語りかけて答えを返してくれる。
・人工知能@SOFNEC(自然言語で画像認識+行動)
色のついた物体に位置関係の指令を自然言語で伝えると、良きに計らって物体を把持して移動させてくれる。最も技術的には深い所まで実装しているブースであったのではないだろうか。言語解釈のレベルの高さ、外界の物体認識等は他のブースでは見られなかったように思う。注目したい。
・画家@PARTY(写真とって絵画風に画像処理)
完全に画像処理の領域の話だが、Pepper君がやってくれるだけで絵描きさんがやってくれるような雰囲気を出せる。アイディア力です。
・楽器@明和電機(高速で楽器を鳴らす)
ユーザの指令を受けて打楽器を鳴らしていた。いや、何だかかわいかったw
■ライトトニングトーク
懇親会ではライトニングトークがあった。コンテンツ系の人が多い中、産業用ロボットとPepperとの協調を謡ったトークに共感をしている。
【サービス】
ソフトバンクはマジだ、と思わせるファン(?)サービスであった。こうやって若くて元気のある優秀な技術者を鼓舞して、次のイノベーションを誘発するのだろう。
■食事
昼食、夕食が付いていた。球場ばりの生ビールサーバねーさんまでいて、金のかけ方がすげぇ。
■おみやげ
ステッカー、バッジ、そしてTシャツをもらった。やはり金をかけている。小物は普通に嬉しかったが、実は荷物減らしたかったのでTシャツは大変だったのですが、まぁサービスと受け取り感謝することにします。 Tシャツを着る機会が無さそうなのが残念ですね。コテコテのエンジニアの私は作業着で仕事をするし、現場じゃPepperに興味を持つ人もあまりいなそうな気がするので、今は保存用にしておきます。
【最後に】
いやー、刺激になりました。製造業メーカの末端社員が普通に生活していたらとても味わうことの無い体験ができました。飛行機使ってでも行った甲斐がありました。今後もこの子の動向は見守りたいですね。当選して招待くださったソフトバンクさんに感謝です。 お次はSDKをいじくらないとですね。がっつり触るとこまで行けて気が向いたらポストします。やりたいことは順番にやります。
【概要】
■目的:Pepperの開発環境、開発舞台裏の公開、先行開発の展示等
■HP:http://www.pepper-techfes.jp/
■日時:2014/09/20 10:30~17:00(懇親会:17:30-19:00)
■場所:ベルサール渋谷ガーデン
■備考:
集客は1000人。抽選で選考。多分経歴や作品の項目は見られているかも。
SDKの配布あり(ハードウェア情報公開)。
先行予約抽選200名。当日1名抽選でお持ち帰り。
昼食、懇親会あり。おみやげあり。
【所感】
■総括
・大盛況であった。予約は初日ですでに500件。1台56万のロボットにこれほどの人が食いつくとは、とんでもないことである。とかくソフトバンクは話題性を作るのがうまい。タイミングといい、技術的なレベルといい。
・開発者フレンドリ感が半端ない。頭金20万+月1万×3年=計56万で手に入る。開発中壊れたら無償で修理。ペイするはずが無い。開発者思いの良心的な体制に涙ものでしょう。
http://www.softbank.jp/robot/special/tech/reserve/
・Web系、コンテンツ系の食いつきが大きく、雰囲気としては、スマホアプリが流行り始めたあたりに似ている。
・コテコテのロボットエンジニアや研究者は少数派。私のような田舎者には恐れ多い(?)空間だったが、逆を取ればチャンス。
・SDKはソフト屋としては至れり尽くせりな開発環境であった。
・先立って開発されたコンテンツのブースは未来を感じさせるものであった。スマホ感覚でアプリを入れられる世界も面白そうだけど、ガチなエンジニアや研究者介入すればもっと色々なことができるだろう。
・現状会話は作りこみのレベルで、感情の形成に直接結びつくような議論はまだ感じなかった。今後に期待。
■ハードウェア
・まじでハードは分からないが、技術的には従来レベルのものを精巧に組み合わせて製品化したのだと思う。マイク、タッチセンサ、カメラ、3Dセンサ、ジャイロセンサ…。どれを取っても新しいものではない。しかし、それがオールインワンになっていることに非常に価値がある。特にソフト屋に自分にとってはハードがこれほど揃っているなんて夢のようである。
・あれだけのセンサやアクチュエータを搭載したメカメカの塊を、コンシューマ向けの製品化までこぎつけたこと自体が、ソフトバンクの持つ総合力なのだろう。
■SDK
・Pepper自体の製品化はもちろん驚きだが、SDKの方が革命的だろう。従来、ロボットの開発環境というと、難解でクリエータさんが触れるレベルのものではなかったはずだ。その難しさはロボット開発者が補完していて、しかもその難しさを習得すること自体がロボット開発者のアイデンティティともなっていたように思う。
・そこを、ボックスと矢印をぺたぺたして、ちょっと動作を定義するだけの簡易なGUIで操作でき、かつ深いところはプログラミング言語で詳細に記述できるというのだから、クリエータ、エンジニア、研究者まで誰でも食いつける土台はできている。
・実はこのSDK、ソフトバンクがロボット事業で提携しているAldebaran Robotics社のChoregrapheというSDKを採用している。つまり、この洗練されたロボットSDKは既に存在していたわけで、これをAndroidSDKばりにオープン化すればビジネスになると睨んだソフトバンクはやはりすげー。来年くらいからこの手の本が売れるんだろうなー。
・自身を守るための基本動作が根底のレイヤで定義されている。衝突回避や転倒防止など。機能を実装する側がこれらを意識せずに開発に集中できる枠組みができている。なんだこれは。どんだけソフト屋に優しいんだ。
■サポート
・開発中の故障に関する修理は3年間無償らしい。月額の料金に組み込まれているよう。プレゼンで「ロボットは壊れるものです」と、家電とかパソコンでは考えられないようなフレーズを口にしたうえで、でもちゃんと面倒見ますよときて技術者を安心させるとは、うまいプレゼンです。
・技術サポートをするアトリエができるらしい。田舎ものの私には関係な(ry
・SDKのコミュニティがあるらしい。これは使えそう。
【展示スペース】
・IT関連分野に広く例題があったが、基本的には従来技術をPepperに適用・応用した事例である(技術なのか?といえるようなトンデモ展示もあったがw)。逆に言えば、既存技術を容易に適用しやすい開発環境が整備されているということである。その適用媒体がPepperになるだけで、未来を感じさせるような雰囲気をプンプンかもし出しているところに、彼らの存在意義がある。
■出展内容
・オープニングショー@HDMI(複数のPepperが踊ってた)
相互連携しているような感じがした。
・シンガー@YAMAHA(歌詞から曲生成 VOCALOID)
筐体がいるだけで楽しさ倍増な感じ。
・会話@1-10design(複数Pepeprと会話)
複数台いるとPepperの独特の世界感が出来上がって面白かった。
・家電制御@ユカイ(Pepperに家電制御を指示)
杖型の媒体をインタフェースとして家電を操作。未来感が出ていた。
・教育@Tryon(Pepperと一緒に遊びながら学ぶ)
教育用途は想定していた。語学とか。
・Webサービス@Yahoo(Pepper経由でYahooコンテンツ)
写真が無いorz... タブレットにYahooショッピングとかのアイコンがあった。
・データベース連携@IBM(IBM Watsonと連携して質問応答)
シークレットブースだったよう。当日公開された。人が写ってしまったので写真自粛。Pepperの筐体自体は今回はあまり関係ないけど。自然言語で語りかけて答えを返してくれる。
・人工知能@SOFNEC(自然言語で画像認識+行動)
色のついた物体に位置関係の指令を自然言語で伝えると、良きに計らって物体を把持して移動させてくれる。最も技術的には深い所まで実装しているブースであったのではないだろうか。言語解釈のレベルの高さ、外界の物体認識等は他のブースでは見られなかったように思う。注目したい。
・画家@PARTY(写真とって絵画風に画像処理)
完全に画像処理の領域の話だが、Pepper君がやってくれるだけで絵描きさんがやってくれるような雰囲気を出せる。アイディア力です。
・楽器@明和電機(高速で楽器を鳴らす)
ユーザの指令を受けて打楽器を鳴らしていた。いや、何だかかわいかったw
■ライトトニングトーク
懇親会ではライトニングトークがあった。コンテンツ系の人が多い中、産業用ロボットとPepperとの協調を謡ったトークに共感をしている。
【サービス】
ソフトバンクはマジだ、と思わせるファン(?)サービスであった。こうやって若くて元気のある優秀な技術者を鼓舞して、次のイノベーションを誘発するのだろう。
■食事
昼食、夕食が付いていた。球場ばりの生ビールサーバねーさんまでいて、金のかけ方がすげぇ。
■おみやげ
ステッカー、バッジ、そしてTシャツをもらった。やはり金をかけている。小物は普通に嬉しかったが、実は荷物減らしたかったのでTシャツは大変だったのですが、まぁサービスと受け取り感謝することにします。 Tシャツを着る機会が無さそうなのが残念ですね。コテコテのエンジニアの私は作業着で仕事をするし、現場じゃPepperに興味を持つ人もあまりいなそうな気がするので、今は保存用にしておきます。
【最後に】
いやー、刺激になりました。製造業メーカの末端社員が普通に生活していたらとても味わうことの無い体験ができました。飛行機使ってでも行った甲斐がありました。今後もこの子の動向は見守りたいですね。当選して招待くださったソフトバンクさんに感謝です。 お次はSDKをいじくらないとですね。がっつり触るとこまで行けて気が向いたらポストします。やりたいことは順番にやります。
2014年8月15日金曜日
2014年7月23日水曜日
2014年7月13日日曜日
2014年7月8日火曜日
2014年7月5日土曜日
2014年7月4日金曜日
2014年7月1日火曜日
2014年6月27日金曜日
2014年6月26日木曜日
2014年6月22日日曜日
2014年6月19日木曜日
2014年6月18日水曜日
2014年6月17日火曜日
2014年6月16日月曜日
2014年6月14日土曜日
C++/CLI フォームアプリとOpenGLの連携(フォームへのレンダリングとGUI操作)
【はじめに】
前エントリの知識をベースに、フォームアプリとOpenGLを連携させます。
完成イメージ図です。
初期画面は何も出ません。Startを押すと画像が表れ図形が回転します。
Stopを押すと図形がとまります。
これを作るために必要な項目を列挙すると次の通りです。
1. ピクチャコントロールを追加する。
まず、前エントリのようにフォームアプリの新規作成まで行います。フォームデザイナにピクチャコントロールとボタンを追加しておきましょう。
ペイント用のイベントハンドラを追加しておきます。プロパティでイベントハンドラ一覧を表示します。雷のようなマークを選択します。
下のほうにPaintがあるので、これをダブルクリックします。
ソースコードに自動でイベントハンドラが追加されます。
ひとまず、こんなところで良しとします。
2. ピクチャコントロールにOpenGLの描画ができるようにする。
このテーマの肝です。glu以外使用しないでやりたいと思います。今までGLUTにお任せしておけば勝手にやってくれいた部分ですね。
次のサイトを大いに参考にさせていただきました。ありがとうございました。VC++の.NET Frameworkアプリケーションの子ウインドウでOpenGL
このサイトのソースコードを解釈する形で話を進めていきます。
大事なのは、attach_GL()関数です。ここでピクチャボックスのハンドルとGLレンダリングコンテキストを関連付けます。
その部分を抜粋してみます。
ここまで分かればあとは普通のOpenGLの描画を設定してしまえばOKです。
3. OpenGLの設定と描画関数を作成する。
先ほどのVC++の.NET Frameworkアプリケーションの子ウインドウでOpenGLを参考にさせていただき、OpenGL描画用のクラスを作りました。
せっかくなので描画する図形だけ少し変えました。gluCylinder()を使いました。次のサイトを参考にしました。GLUTによる「手抜き」OpenGL入門
一応ソースを公開します。後のイベントハンドラへの登録を意識したつくりになっています。
COpenGL.h
COpenGL.cpp
4. Timerコントロールを追加する。
コントロールからTimerを選択して、デザイナにドラッグアンドドロップします。プロパティを開き、「動作→Enable」をTrueにします。
同じくプロパティからイベント一覧を表示し、Tickをダブルクリックします。Intervalごとに呼ばれるイベントハンドラが定義されます。ここにOPenGLの描画を行えばアニメーションになります。
最終的にはOpenGLとの連携にもって行きたいです。
5. Buttonコントロールで挙動を設定(完成)
前エントリ同様に、Buttonのイベントハンドラを追加します。二つのボタンで動画フラグの入り切りを切り替えます。
これで完成です。Form側のソースコードを公開し、終了です。
前エントリの知識をベースに、フォームアプリとOpenGLを連携させます。
完成イメージ図です。
初期画面は何も出ません。Startを押すと画像が表れ図形が回転します。
Stopを押すと図形がとまります。
これを作るために必要な項目を列挙すると次の通りです。
- ピクチャコントロールを追加する。 これがないと話が始まりません。
- ピクチャコントロールにOpenGLの描画ができるようにする。 OpenGLのレンダリングコンテキストをピクチャコントロールに関連付けます。
- OpenGLの設定と描画関数を作成する。 普通のOpenGLの処理です。
- Timerコントロールを追加する。 動画を描画できるようにします。
- Buttonコントロールで挙動を設定(完成)。 ボタンで動画のフラグを制御します。
1. ピクチャコントロールを追加する。
まず、前エントリのようにフォームアプリの新規作成まで行います。フォームデザイナにピクチャコントロールとボタンを追加しておきましょう。
ペイント用のイベントハンドラを追加しておきます。プロパティでイベントハンドラ一覧を表示します。雷のようなマークを選択します。
下のほうにPaintがあるので、これをダブルクリックします。
ソースコードに自動でイベントハンドラが追加されます。
ひとまず、こんなところで良しとします。
2. ピクチャコントロールにOpenGLの描画ができるようにする。
このテーマの肝です。glu以外使用しないでやりたいと思います。今までGLUTにお任せしておけば勝手にやってくれいた部分ですね。
次のサイトを大いに参考にさせていただきました。ありがとうございました。VC++の.NET Frameworkアプリケーションの子ウインドウでOpenGL
このサイトのソースコードを解釈する形で話を進めていきます。
大事なのは、attach_GL()関数です。ここでピクチャボックスのハンドルとGLレンダリングコンテキストを関連付けます。
その部分を抜粋してみます。
// a. ピクチャボックスコントロールからハンドルを取得 if (!(hWnd=(HWND)(pbox->Handle).ToInt32())) { MessageBox(NULL, (LPCTSTR)("COpenGL::attach_GL called with 0 (NULL)"), NULL, MB_OK); return false; } // b. ハンドルからデバイスコンテキストを取得 if (!(hdc=GetDC(hWnd))) { MessageBox(NULL, (LPCTSTR)("COpenGL::attach_GL GetDC(hWnd)"), NULL, MB_OK); return false; } wglMakeCurrent(NULL, NULL); //おまじない // c. ピクセルフォーマットの設定 PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 24, // 24-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 32, // 32-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; int pixFormat; // デバイスコンテキストにマッチするピクセルフォーマットを取得 if((pixFormat = ChoosePixelFormat(this->hDC, &pfd)) == NULL) { MessageBox(NULL, (LPCTSTR)("Error: ChoosePixelFormat() in COpenGL::setPixelFomat()"), NULL, MB_OK); return false; } // デバイスコンテキストにピクセルフォーマットを設定 if((SetPixelFormat(this->hDC, pixFormat, &pfd)) == NULL) { MessageBox(NULL, (LPCTSTR)("Error: SetPixelFormat() in COpenGL::setPixelFomat()"), NULL, MB_OK); return false; } // d. デバイスコンテキストからOpenGLレンダリングコンテキストを取得 if (!(hglrc = wglCreateContext(hdc))) MessageBox(NULL, (LPCTSTR)("COpenGL::attach_GL wglCreateContext(hdc)"), NULL, MB_OK) return false; } // e. 取得したOpenGLレンダリングコンテキストをカレントに設定 if(!wglMakeCurrent(hdc, hglrc)) { MessageBox(NULL, (LPCTSTR)("COpenGL::attach_GL wglMakeCurrent(hdc, hglrc)"), NULL, MB_OK); return false; } |
- ピクチャボックスコントロールからハンドルを取得 .Netのピクチャコントロールから、Windowsのウィンドウハンドルを取得します。ハンドルとは、そのウィンドに一意に対応付くIDみたいなものです。これをしないと次のデバイスコンテキストを取得できません。
- ハンドルからデバイスコンテキストを取得 先ほど取得したハンドルからデバイスコンテキストを取得します。デバイスコンテキストとは、描画を行うためのキャンパスと描画材料のセットです。こちらのサイトを読ませていただきました。Kab Studio - デバイスコンテキストとハンドル。
- ピクセルフォーマットの設定 OS側の描画パラメータを、OpenGLに合わせて設定してあげるOSとOpenGLの橋渡し的な役割のよう。色空間の定義や、色バッファの分解能などを設定しておきます。こちらのサイトを参考にさせていただきました。sonson@Picture&Software - [OpenGL] ピクセルバッファ
- デバイスコンテキストからOpenGLレンダリングコンテキストを取得 OSのデバイスコンテキストを、OplenGL用のデバイスコンテキストに切り替えます。
- 取得したOpenGLレンダリングコンテキストをカレントに設定 カレントコンテキストを設定します。これは複数のウィンドウに描画をしたい場合などに役に立ちます。
水彩画を描きたいと思ったときに、油絵用の画材セットでは書けません。描画するキャンパスに適した画材をセット用意する必要があります。
ここまで分かればあとは普通のOpenGLの描画を設定してしまえばOKです。
3. OpenGLの設定と描画関数を作成する。
先ほどのVC++の.NET Frameworkアプリケーションの子ウインドウでOpenGLを参考にさせていただき、OpenGL描画用のクラスを作りました。
せっかくなので描画する図形だけ少し変えました。gluCylinder()を使いました。次のサイトを参考にしました。GLUTによる「手抜き」OpenGL入門
一応ソースを公開します。後のイベントハンドラへの登録を意識したつくりになっています。
COpenGL.h
#pragma once #include <Windows.h> #include <GL/GLU.h> #include <math.h> #pragma comment (lib, "OpenGL32.lib") // wglAPIで必要 #pragma comment (lib, "GLU32.lib") #pragma comment (lib, "user32.lib") // win32APIで必要 #pragma comment (lib, "gdi32.lib") // setPixelFormat等で必要 ref class COpenGL { public: COpenGL(void); virtual ~COpenGL(void); bool attachGL(System::Windows::Forms::PictureBox^ inPicBox); void detachGL(void); void resizeScene(void); void paintWindow(void); private: void setPerspectivePrm(const int cInWinWIdth, const int cInWinHeight, const int cInAngle, const int cInZNear, const int cInZFar); void callGluPerspecrive(void); bool setPixelFomat(void); void renderScene(void); private: HWND hWnd; HDC hDC; HGLRC hGLRC; int winWidth; int winHeight; int angle; int zNear; int zfar; int tick; bool tickEnagle; }; |
COpenGL.cpp
#include "COpenGL.h" static const int scAngle = 40; static const int scZNear = 100; static const int scZFar = 1300; COpenGL::COpenGL( void ) { this->tick = 0; this->tickEnagle = false; } COpenGL::~COpenGL( void ) { } bool COpenGL::attachGL( System::Windows::Forms::PictureBox^ inPicBox ) { bool rc = false; do { // ピクチャボックスコントロールからハンドルを取得 if(!(this->hWnd = (HWND)(inPicBox->Handle).ToInt32())) { MessageBox(NULL, (LPCTSTR)("Error: (inPicBox->Handle).ToInt32() in COpenGL::attatchGL"), NULL, MB_OK); rc = true; break; } // ハンドルからデバイスコンテキストを取得 if(!(this->hDC = GetDC(this->hWnd))) { essageBox(NULL, (LPCTSTR)("Error: GetDC() in COpenGL::attatchGL"), NULL, MB_OK); rc = true; break; } // おまじない wglMakeCurrent(NULL, NULL); // ピクセルフォーマットの設定 if(this->setPixelFomat()) { MessageBox(NULL, (LPCTSTR)("Error: COpenGL::setPixelFomat() in COpenGL::attatchGL"), NULL, MB_OK); rc = true; break; } // デバイスコンテキストからOpenGLレンダリングコンテキストを取得 if(!(this->hGLRC = wglCreateContext(this->hDC))) { MessageBox(NULL, (LPCTSTR)("Error: wglCreateContext() in COpenGL::attatchGL"), NULL, MB_OK); rc = true; break; } // 取得したOpenGLレンダリングコンテキストをカレントに設定 if(!wglMakeCurrent(this->hDC, this->hGLRC)) { MessageBox(NULL, (LPCTSTR)("Error: wglMakeCurrent() in COpenGL::attatchGL"), NULL, MB_OK); rc = true; break; } } while(false); // 視野パラメータ設定 this->setPerspectivePrm(inPicBox->Width, inPicBox->Height, scAngle, scZNear, scZFar); // 視野設定 this->callGluPerspecrive(); return rc; } void COpenGL::detachGL( void ) { wglMakeCurrent(NULL, NULL) ; if (this->hGLRC) wglDeleteContext(hGLRC); if (hDC) ReleaseDC(hWnd, hDC); } void COpenGL::resizeScene( void ) { this->callGluPerspecrive(); } void COpenGL::paintWindow( void ) { if(this->tickEnagle == true) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); double leye=700.0; double dip=0.65; double rot=0.5; //dip,rot[rad] double ly,lxz,lx,lz; ly=leye*sin(dip); lxz=leye*cos(dip); lx=lxz*sin(rot); lz=lxz*cos(rot); gluLookAt(lx,ly,lz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glClearColor(0,0,0.5,0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); // depth check } renderScene();//render here SwapBuffers(this->hDC); } void COpenGL::setPerspectivePrm( const int cInWinWIdth, const int cInWinHeight, const int cInAngle, const int cInZNear, const int cInZFar ) { this->winWidth = cInWinWIdth; this->winHeight = cInWinHeight; this->angle = cInAngle; this->zNear = cInZNear; this->zfar = cInZFar; } void COpenGL::callGluPerspecrive( void ) { glViewport(0, 0, this->winWidth, this->winHeight); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(this->angle, (GLdouble)this->winWidth/(GLdouble)this->winHeight, this->zNear, this->zfar); } bool COpenGL::setPixelFomat( void ) { bool rc = false; PIXELFORMATDESCRIPTOR pdf = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 24, // 24-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 32, // 32-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; int pixFormat; do { // デバイスコンテキストにマッチするピクセルフォーマットを取得 if((pixFormat = ChoosePixelFormat(this->hDC, &pdf)) == NULL) { MessageBox(NULL, (LPCTSTR)("Error: ChoosePixelFormat() in COpenGL::setPixelFomat()"), NULL, MB_OK); rc = true; break; } // デバイスコンテキストにピクセルフォーマットを設定 if((SetPixelFormat(this->hDC, pixFormat, &pdf)) == NULL) { MessageBox(NULL, (LPCTSTR)("Error: SetPixelFormat() in COpenGL::setPixelFomat()"), NULL, MB_OK); rc = true; break; } } while(false); return rc; } void COpenGL::renderScene( void ) { // quadric object を一つ生成する GLUquadricObj *quad = gluNewQuadric(); // 面の塗り潰しを指定する(線画ではなく陰影をつけた円柱を描く) gluQuadricDrawStyle(quad, GLU_FILL); // スムースシェーディングを行うよう設定する gluQuadricNormals(quad, GLU_SMOOTH); glRotatef((GLfloat)this->tick, 1, 0, 0); this->tick += 5; // 側面を描く(stacks = 1) const GLdouble radius = 100; const GLdouble height = 100; const int sides = 20; glColor3f(1, 0, -1); gluCylinder(quad, radius, radius, height, sides, 1); // height の高さに上面を描く glPushMatrix(); glTranslated(0.0, 0.0, height); glColor3f(1, 1, 0); gluDisk(quad, 0.0, radius, sides, 1); glPopMatrix(); // 図形を裏返して描くように設定する gluQuadricOrientation(quad, GLU_INSIDE); glColor3f(0, 1, 1); // 下面を描く gluDisk(quad, 0.0, radius, sides, 1); // 生成した quadlic object を削除する gluDeleteQuadric(quad); } |
4. Timerコントロールを追加する。
コントロールからTimerを選択して、デザイナにドラッグアンドドロップします。プロパティを開き、「動作→Enable」をTrueにします。
同じくプロパティからイベント一覧を表示し、Tickをダブルクリックします。Intervalごとに呼ばれるイベントハンドラが定義されます。ここにOPenGLの描画を行えばアニメーションになります。
最終的にはOpenGLとの連携にもって行きたいです。
5. Buttonコントロールで挙動を設定(完成)
前エントリ同様に、Buttonのイベントハンドラを追加します。二つのボタンで動画フラグの入り切りを切り替えます。
これで完成です。Form側のソースコードを公開し、終了です。
#pragma once #include "COpenGL.h" namespace GLForm { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; /// <summary> /// MyForm の概要 /// </summary> public ref class MyForm : public System::Windows::Forms::Form { public: MyForm(void) { InitializeComponent(); // //TODO: ここにコンストラクター コードを追加します // this->glBase = gcnew COpenGL; this->glRunFlg = this->glBase->attachGL(pictureBox1); } protected: /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> ~MyForm() { if (glRunFlg) glBase->detachGL(); timer1->Enabled=false; delete glBase; if (components) { delete components; } } private: System::Windows::Forms::Button^ button1; private: System::Windows::Forms::Button^ button2; private: System::Windows::Forms::PictureBox^ pictureBox1; private: System::Windows::Forms::Panel^ panel1; private: System::Windows::Forms::Panel^ panel2; private: System::ComponentModel::IContainer^ components; protected: private: /// <summary> /// 必要なデザイナー変数です。 /// </summary> // 自作クラス private: System::Windows::Forms::Timer^ timer1; COpenGL^ glBase; bool glRunFlg; #pragma region Windows Form Designer generated code /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> void InitializeComponent(void) { this->components = (gcnew System::ComponentModel::Container()); this->button1 = (gcnew System::Windows::Forms::Button()); this->button2 = (gcnew System::Windows::Forms::Button()); this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox()); this->panel1 = (gcnew System::Windows::Forms::Panel()); this->panel2 = (gcnew System::Windows::Forms::Panel()); this->timer1 = (gcnew System::Windows::Forms::Timer(this->components)); (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->BeginInit(); this->panel1->SuspendLayout(); this->panel2->SuspendLayout(); this->SuspendLayout(); // // button1 // this->button1->Location = System::Drawing::Point(8, 123); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(77, 22); this->button1->TabIndex = 0; this->button1->Text = L"Start"; this->button1->UseVisualStyleBackColor = true; this->button1->Click += gcnew System::EventHandler(this, &MyForm::button1_Click); // // button2 // this->button2->Location = System::Drawing::Point(7, 160); this->button2->Name = L"button2"; this->button2->Size = System::Drawing::Size(77, 25); this->button2->TabIndex = 1; this->button2->Text = L"Stop"; this->button2->UseVisualStyleBackColor = true; this->button2->Click += gcnew System::EventHandler(this, &MyForm::button2_Click); // // pictureBox1 // this->pictureBox1->Location = System::Drawing::Point(22, 25); this->pictureBox1->Name = L"pictureBox1"; this->pictureBox1->Size = System::Drawing::Size(182, 160); this->pictureBox1->TabIndex = 2; this->pictureBox1->TabStop = false; this->pictureBox1->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::pictureBox1_Paint); // // panel1 // this->panel1->Controls->Add(this->button2); this->panel1->Controls->Add(this->button1); this->panel1->Dock = System::Windows::Forms::DockStyle::Right; this->panel1->Location = System::Drawing::Point(243, 0); this->panel1->Name = L"panel1"; this->panel1->Size = System::Drawing::Size(94, 214); this->panel1->TabIndex = 3; // // panel2 // this->panel2->Controls->Add(this->pictureBox1); this->panel2->Dock = System::Windows::Forms::DockStyle::Fill; this->panel2->Location = System::Drawing::Point(0, 0); this->panel2->Name = L"panel2"; this->panel2->Size = System::Drawing::Size(243, 214); this->panel2->TabIndex = 4; // // timer1 // this->timer1->Enabled = true; this->timer1->Tick += gcnew System::EventHandler(this, &MyForm::timer1_Tick); // // MyForm // this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(337, 214); this->Controls->Add(this->panel2); this->Controls->Add(this->panel1); this->Name = L"MyForm"; this->Text = L"MyForm"; (cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->EndInit(); this->panel1->ResumeLayout(false); this->panel2->ResumeLayout(false); this->ResumeLayout(false); } #pragma endregion private: System::Void pictureBox1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { this->glBase->paintWindow(); } private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { this->glBase->paintWindow(); } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { this->glBase->setTickEnagle(true); } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { this->glBase->setTickEnagle(false); } }; } |
2014年6月13日金曜日
登録:
投稿 (Atom)