2018年6月11日月曜日

embreeの入門に挫折

CGを観察する方向ばかりでしたのですが、開発方面のtipsとして久しぶりの投稿です。

初心者が書いているので、あまり参考にしないでください。

後述にもある通り、グラフィックプログラミング(?)は最近始めました。


2018/6/12 追記:libmmd.dllについて 
2018/9/14 追記:libmmd.dllについて

あくまでもチラチラ見て「ほぉ、そんなもんか、触るか」程度の前段階として考えてください。 embreeというのはintelが作ったOSSのCPUのレイトレです。

最近openGLやレイトレの技術の興味を持っているのでいろいろ触ったりしています。
openGLは和歌山大学、床井教授の GLUTによる「手抜き」OpenGL入門
レイトレーシングはPeter Shirley教授のRay Tracing in One Weekend (Ray Tracing Minibooks Book 1)を和訳した週末レイトレーシング
を途中までしています。
なんか途中ってなぁとは思います。やっている途中でglfwの新しいバージョンが出ましたし。
中身がどうなっているのか知りたい感じなので、写経になっているものをしています。
理論はいろいろ乗ってますけど、実際の計算はどのようにプログラムするかってあんまりわからない気がしますし。あとヘッダーの嵐で理解が危ういですし。

レイトレの基礎の基礎を知るならば週末レイトレーシングはいいと思います、a-mくらいまでは今のところ流し見では説明してくれています。
ヘッダーを書くので初心者の理解としては非常にいいと思います。
只今segment faultで投げ出している。

embreeを参考にしたサイトはembree入門です。
ですが、これをそのまま書くとだめなんですよね。
ver3に上がってAPIの刷新がされています。

私がそれに伴って書いたソースコードは

#include 
#include 
#include 
#include 
#define inf     1e30f
struct Vertex { float x, y, z; };
struct Triangle { int v0, v1, v2; };

int main(void)
{
 /* デバイスを作成 */
 RTCDevice device = rtcNewDevice(NULL);
 /* シーンを作成 */
 RTCScene scene = rtcNewScene(device);

 /* ここでこの後いろいろな処理を行う */
 /* .... */
 
 /* 3角形ジオメトリを作成 */
 RTCGeometry mesh = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
 /*頂点の設定*/
 Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(mesh,RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof(Vertex), 4);
 vertices[0].x = 10; vertices[0].y = 10; vertices[0].z = 0; // 点Aの座標
 vertices[1].x = 10; vertices[1].y = -10; vertices[1].z = 0; // 点Bの座標
 vertices[2].x = -10; vertices[2].y = 10; vertices[2].z = 0; // 点Cの座標
 vertices[3].x = -10; vertices[3].y = -10; vertices[3].z = 0; // 点Dの座標
 
 /*面の設定(用意?)*/
 int tri = 0;
 Triangle* triangles = (Triangle*)rtcSetNewGeometryBuffer(mesh, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(Triangle), 2);
 triangles[tri].v0 = 0; triangles[tri].v1 = 1; triangles[tri].v2 = 3; tri++; // 三角形ABD
 triangles[tri].v0 = 1; triangles[tri].v1 = 2; triangles[tri].v2 = 3; tri++; // 三角形BCD

 unsigned int geomID = rtcAttachGeometry(scene, mesh);


 /*ジオメトリの削除*/
 rtcReleaseGeometry(mesh);

 /* シーンへ登録 */
 rtcCommitGeometry(mesh);

 /*/*レイ交差の初期化*/
 RTCIntersectContext context;
 rtcInitIntersectContext(&context);
 RTCHit rtchit;
 rtchit.geomID = RTC_INVALID_GEOMETRY_ID;

 /* レイを生成する */
 RTCRay rtcray;
 /* レイの始点 */
 rtcray.org_x = 0.0;  // x
 rtcray.org_y = 0.0;  // y
 rtcray.org_z = 20.0; // z
 /* レイの方向 */
 rtcray.dir_x = 0.0;  // x
 rtcray.dir_y = 0.0;  // y
 rtcray.dir_z = -1.0;  // z
 /* 交差判定する範囲を指定 */
 rtcray.tnear = 0.0f;     // 範囲の始点
 rtcray.tfar = inf;  // 範囲の終点.交差判定後には交差点までの距離が格納される.
 rtcray.time = 0;

 /* 交差判定 */
 RTCRayHit ray;
 rtcIntersect1(scene, &context, &ray);
 if (rtchit.geomID == RTC_INVALID_GEOMETRY_ID)
 {
  /* 交差点が見つからなかった場合 */
  std::cout << "Reject." << std::endl;
 }
 else
 {
  /* 交差点が見つかった場合 */
   std::cout << "Intersect" << std::endl;
  
 }
 
 /* シーンを削除 */
 rtcReleaseScene(scene);
 /* デバイスを削除 */
 rtcReleaseDevice(device);
 system("pause");
 return 0;
}
}
です。 

 躓いているのが、「レイと三角形との交差判定」なんですよね。
 RTCHitで判定すると思うのですが、初期化したデータがそのまま受け継がれているんですよね。


 プログラムの解説なのですが、
引用元の最初に当たる、初期化と終了処理は


#include 
#include 
#include 

int main(void)
{
 /* デバイスを作成 */
 RTCDevice device = rtcNewDevice(NULL);
 /* シーンを作成 */
 RTCScene scene = rtcNewScene(device);

 /* シーンを削除 */
 rtcReleaseScene(scene);
 /* デバイスを削除 */
 rtcReleaseDevice(device);
 return 0;
}
 
シーンの作成にあたり、embree2と違って、deviceの選択のみです。
embree3では他はシーンの品質の左右のみのようです。


次に三角形の作成なのですが、tutorialsのtrianglesをパクり参考にしましたので、構造体になっています。
ジオメトリの名前をmeshにしているのはgeomIDとRAYHitのgeomIDで使いたかったからです。



struct Vertex { float x, y, z; };
struct Triangle { int v0, v1, v2; };

 /* 3角形ジオメトリを作成 */
 RTCGeometry mesh = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
 /*頂点の設定*/
 Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(mesh,RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof(Vertex), 4);
 vertices[0].x = 10; vertices[0].y = 10; vertices[0].z = 0; // 点Aの座標
 vertices[1].x = 10; vertices[1].y = -10; vertices[1].z = 0; // 点Bの座標
 vertices[2].x = -10; vertices[2].y = 10; vertices[2].z = 0; // 点Cの座標
 vertices[3].x = -10; vertices[3].y = -10; vertices[3].z = 0; // 点Dの座標
 
 /*面の設定(用意?)*/
 int tri = 0;
 Triangle* triangles = (Triangle*)rtcSetNewGeometryBuffer(mesh, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(Triangle), 2);
 triangles[tri].v0 = 0; triangles[tri].v1 = 1; triangles[tri].v2 = 3; tri++; // 三角形ABD
 triangles[tri].v0 = 1; triangles[tri].v1 = 2; triangles[tri].v2 = 3; tri++; // 三角形BCD

 unsigned int geomID = rtcAttachGeometry(scene, mesh);


 /*ジオメトリの削除*/
 rtcReleaseGeometry(mesh);

 /* シーンへ登録 */
 rtcCommitGeometry(mesh);

ジオメトリの作成にあたって、引数でジオメトリのタイプを設定し、
ジオメトリに対して、頂点や面の数、場所を書き込んでいます。


レイの送受なのですが、
embree3ではembree2のRTCRayの役割がRTCrayとRTCHitに変わっています。
私はここのRTCHitの扱いがわかりませんでした。


    /*レイ交差の初期化*/
 RTCIntersectContext context;
 rtcInitIntersectContext(&context);
 RTCHit rtchit;
 rtchit.geomID = RTC_INVALID_GEOMETRY_ID;

 /* レイを生成する */
 RTCRay rtcray;
 /* レイの始点 */
 rtcray.org_x = 0.0;  // x
 rtcray.org_y = 0.0;  // y
 rtcray.org_z = 20.0; // z
 /* レイの方向 */
 rtcray.dir_x = 0.0;  // x
 rtcray.dir_y = 0.0;  // y
 rtcray.dir_z = -1.0;  // z
 /* 交差判定する範囲を指定 */
 rtcray.tnear = 0.0f;     // 範囲の始点
 rtcray.tfar = inf;  // 範囲の終点.交差判定後には交差点までの距離が格納される.
 rtcray.time = 0;

レイの生成に関しては全く変わっていないです。
RTCHitを後述のifなどで使うにあたり、初期化しなくてはならないのですが、何をどうしているのかいろいろ見てもさっぱりでした。


コピペです。交差判定は説明書を見て書き換えた形です。

 /* 交差判定 */
 RTCRayHit ray;
 rtcIntersect1(scene, &context, &ray);
 if (rtchit.geomID == RTC_INVALID_GEOMETRY_ID)
 {
  /* 交差点が見つからなかった場合 */
  std::cout << "Reject." << std::endl;
 }
 else
 {
  /* 交差点が見つかった場合 */
   std::cout << "Intersect" << std::endl;
  

上記のプログラムを実行した場合、普通にRejectと出ますが、
レイの交差初期化で
 rtchit.geomID = geomID;
とした場合、Intersectと出ます。

わからないなりに適当に書いてしまった缶はありますが、embree3を触ろうかなぁと思っている方の気持ちを押すだけの手助けになれば幸いです。
技術的な視点はないので、気になった方は各自でググってください。もうギブ。

それにしても、意外と奈良先端技術大学院大学って近いんですね、クソ遠いかと思っていたのですが、そうでもなかったです。

参考
embree入門
embree公式
説明書


追記:libmmd.dllがないためエラーが出る場合
私の環境ではでました。
検索すると、c4dの例が多いみたいです。
検索した結果ではMSのVS再配布パッケージをインストールすれば解消することが多いようですが、ダメな場合は、intelのc++再配布パッケージをダウンロードすると解消すると思います。
嫌ならば、Embree Example Rendererからlibmmd.dllだけ取り込んでぶっこむのもありかもしれません、保証はしません、ご了承ください。 

コメント欄にてうしおさんがlibmmd.dllについて述べられています。
ありがとうございます。
3.10 3.21alphaなどを使うと良いそうです。

githubの存在をすっかり忘れてました...どこからdlするのかって話になりますね...。

2018年6月8日金曜日

VR Zoneにて


前に似たような記事では、今はなきジョイポリスでSIMVRの「BLASTxBLAST」(その時の記事)で体験しました。





今回はVR Zone Umedaで「アーガイルシフト」というVRシネマティックアトラクションを体験しました。


内容はVRを用いた体感型映画みたいな感じですね。
何かしら敵機体破壊の操作方法が言われますが、まぁそういうアクションはあって意味がないような感じですね。

ロボットのコックピットに乗って、隣に可愛いアシスタントがいて、 動きを感じながら空中を速く爽快に進んでいくっていうのは、まぁ~すごい、良い、好き、かっこいい、ロマンです。

ガンダムの戦場の絆とか体験したことがない(ガンダム勢怖い)ですので、比較はできませんが、xに240度位、yに140度位でUIが浮かんでいて、足があるっていうのが臨場感ありまくりでした。

ただ、7mで1000円は高く、コンテンツ自体面白くて短く感じてしまうのは難点ですね。
また、トロッコ式でほぼなにもしないので、何度も体験したくなる感じは低いですねぇ...。
 
個人的には2000円30mで箱庭を自由に闊歩して、ジョイスティックで移動と照準を合わした攻撃で基地制圧とかがあって、スコアアタックなると数回はプレイすると思いました。
BLASTxBLASTの操作のViveコントローラーは流石にパスで、重くて死ぬ。
作るの死ぬほど面倒そうです、デバックとかヤバそう。

やはり、前のSIMVRと同じでかなりViveの画像の粗さ、網目状のやつが気になりますね...。
これはHMDの使用で仕方がないので、Vive Proか世代交代の時期に期待ですかね。

VR Osakaができれば、ユーザーの自由度が高い
マリオカート アーケードグランプリVR
VR-ATシミュレーター 装甲騎兵ボトムズ バトリング野郎
をやってみたいですね、マリカ以外全く原作知りませんが。

百聞は一見にしかずですので、機会があれば触ってみると価値観は変わりますね。
上でなんだかんだ言っておきながらすごく楽しかったですw 
続きプレイしたいですわ...Steamで...。