はじめに

HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html )

 HGIMG4の説明は、リンク先のガイドに全て書かれています。 ざっと目を通したので読みながら書いたメモを公開してみました。 解説あり予想あり感想ありのごちゃ混ぜ状態です。 参考にされる方は、自己責任でお願いします。

注意:このページは書きかけです。新しくわかったことがあると書き足すことがあります。

HGIMG4

9.HGIMG4ランタイムの制限 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#RUNTIME_NOTICE )

 HGIMG4は、HSP3Dishの機能は内包した上で3Dなど高機能な描画機能を持っています。 Android/iOSなどにも対応しています。 HSP3Dishが持つ命令をすべてサポートしていますが、同時に制約も引き継いでいます。 詳しくはこちら。

座標系は、右手座標系。

  • +Y:天井方向
  • +Z:手前方向

3Dモデル

 FBX形式を謳っているものの実際はそのまま読み込めず、後述する方法でGPB形式に変換して使用します。

対応形式:GPB形式

ゲームフレームワーク・エンジン「gameplay3D( http://www.gameplay3d.io/, https://github.com/gameplay3d/gameplay )」で使用されている形式。

GPB形式を構成するファイル

  • resフォルダ:GPB形式ファイル一式を格納する専用フォルダ
  • .gpbファイル:モデルとアニメーションクリップ
  • .materialファイル:マテリアル情報
  • .pngファイル:テクスチャ画像

 マテリアル情報(.materialファイル)には、次のような情報が記述されている。 なお、テキストファイルなのでメモ帳などで編集できる。GPB converterでも編集が可能。

  • マテリアル(質感)
  • ライティング設定
  • シェーダーファイルの指定

3Dモデルデータの準備

HGIMG4 Unity連携ガイド ( http://www.onionsoft.net/hsp/v36/doclib/hgimg4_unity.html )

 FBX形式、VRM形式をGPB形式に変換して使用します。 変換方法の説明は、Unityを使用する方法が記載されています。 この方法なら、Unityを使ってFBX形式に出力できるモデルならどのファイル形式でもHGIMG4で出力できるということになりそうですね。 Unityならモーションデータもたくさん配布されているので便利が良さそうです。

FBX形式 → GPB形式
Unity(FBX Exporter) → GPB converter(gpbconv.exe)

VRM形式 → GPB形式
Unity(UniVRM) → Unity(FBX Exporter) → GPB converter(gpbconv.exe)

GPB converter

 FBX形式をGPB形式に変換するコンバータ GPB converter(gpbconv.exe)の起動は、下記のどちらか好きな方で行うことが出来る。

  • HSPスクリプトエディタの「ツール」メニューから「HGIMG4ツールを開く」を選択。
  • gpbconv.exe を実行。

用語解説

ちょっと難しそうな用語をまとめてみました。

アニメーションクリップ
モデルデータ(.gpbファイル)に格納された、モデルを動かすモーションデータのこと。 1つのgpbファイルには、1つのアニメーションデータが格納できる。 アニメーションデータから任意の区間を切り取ったものがアニメーションクリップ。
ノードオブジェクト
「ノード」「オブジェクト」とも呼ばれる。3Dモデルやカメラなど。 HGIMG4の操作対象で、番号(ID)で管理・操作する。
シーン
複数の「ノードオブジェクト」を含めた場全体を指す。 「シーン」に登録された「ノードオブジェクト」がレンダリング(描画)の 対象となる。 1つだけ存在し、gpreset命令でリセットして使用します。描画はgpdraw命令。
クローン
敵雑魚キャラや弾丸など、同じモデルを複数配置するような場合に活躍する機能。
スプライトオブジェクト
3Dのノードオブジェクトの2D版のようなもの。Dish/HGIMG4を使わなくても使用できる。
カメラ
ノードオブジェクトの1つ。シーンがリセットされるとデフォルトのカメラが自動作成される。 カメラは複数作成して配置することが出来る。 デフォルトのカメラには、GPOBJ_CAMERAマクロを使用してアクセスする。 シーン内に設置したカメラで撮影した映像がウィンドウ上に描画される。
視野(FOV)
カメラの視野の広さ。画角を角度で表したもの。
Zクリッピング/ニアクリップZ値/ファークリップZ値
描画される奥行きの範囲(距離)。 ニアクリップより近い場所にあるオブジェクトは描画されない。 ファークリップより遠い場所にあるオブジェクトは描画されない。
表示範囲
平行投影(Orthographic)
遠近法で描画されないようにする設定。遠くのものも近くのものも同じ大きさで描画される。
ライト(光源)オブジェクト
ノードオブジェクトの1つ。ヌルノードや3Dモデルにライト機能を取り付けることが出来る。 負荷が高いので、あらかじめ個数制限を設定して使用する。 デフォルトのライトには、GPOBJ_LIGHTマクロを使用してアクセスする。
ヌルノード
空のノードオブジェクト。 カメラやライトなどモデルを持つ必要のないノードを作成する場合に使用する。
ディレクショナルライト
方向性ライト、平行ライトなどと呼ばれる。光源が極めて遠く、単一の方向から平行に降り注ぐ光。太陽光など。 シーンがリセットされると自動的に作成される。
アンビエントカラー
アンビエント(環境光)。モデル対して全方向から当たる特殊な光。

基本的な書き方

12.初期化と描画の方法 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#INITALIZE )

最初に初期化(gpreset)した後は、通常通りredrawで前後を挟んで描画すればいいだけです。 redraw 0 で画面クリアまでしてくれるので、boxfが不要です。


#include "hgimg4.as"
gpreset	; hgimgの初期化

	…

*main
	;	描画メイン
	;
	redraw 0	; 描画開始(画面クリア)

	;	
	;	各種描画を行なう
	;	

	redraw 1	; 描画終了
	await 1000/60	; 時間待ち(60フレーム/秒)
	goto *main

フレームレートの取得

32.フレームレートの取得 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#FRAMERATE )

 HDLのgetreqには記載がありませんが、SYSREQ_FPSオプションでFPS値が取得できます。 HDLのsetreqには記載がありませんが、SYSREQ_VSYNCオプションでVSYNC待ち(垂直同期待ち)が設定できます。 「setreq SYSREQ_VSYNC,1」はメインループに入る前に1回実行すればいいようです。

 適用するとawaitを設定しなくても60FPSで動作するようになります。 ただしawaitを全く実行しないとウィンドウが操作できなくなるのでawaitを必ず入れておく必要があります。 待機時間は 0 ~ SYSREQ_VSYNCの待機時間 で設定してください。

includeまとめ

#includeだけでもいくつか説明が出てきているのでまとめ。 特に問題なければ、#include "hgimg4.as"を選んでおけば良さそうですね。

#include "hgimg4dx.as"
HGIMG4 DirectX9版ランタイムを使用する場合。
同梱が必要なファイル:d3dcompiler_47.dll、libEGL.dll、libGLESv2.dll
#include "hgimg4.as"
OpenGL版ランタイムを使用する場合。
同梱が必要なファイル:なし
#include "mod_posteffect.as"
ポストエフェクトモジュール。
オフスクリーンバッファを使用します。
#include "mod_gputil.as"
3Dモデルが持っている親子関係など複雑な階層(ノード)情報を取得してアクセス可能にするモジュール。

カメラ

17.カメラの設定 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#CAMERA )

 カメラを通した映像がウィンドウ上に描画されるイメージです。 とはいえ厳密には無制限に遠いものまで描画できるわけではなく、画角とクリッピング(距離)で指定された扇状の空間内にあるオブジェクトだけが描画されます。 シーンをリセットすると、デフォルトのカメラが配置されるので深く考えなくても気にせず使えます。

 また、カメラは複数配置することができ、切り替えて使用できます。

ライト

18.ライトの設定 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#LIGHT )

 ディレクショナルライト、ポイントライト、スポットライトなどから複数設定できます。 ポイントライト、スポットライトは、数が多いとGPUの計算負荷につながるので、無駄に配置しないようにしてください。

衝突判定

19.コリジョングループ設定と衝突検知 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#COLLISION )

 不要な衝突処理の回数を減らすため、コリジョングループを作って管理します。Obaqの衝突判定と同じ要領のようです。 getcoliを使用すると、「オブジェクトID」のノードオブジェクトが、「衝突を検出する対象となるグループ値」に属するオブジェクトと衝突したことを検出できます。

 例えば、このように設定した場合、敵(1)は敵攻撃(2)に当たっても衝突を検出しません。 また自機(4)は敵(1)と敵攻撃(2)に当たると衝突を検出します。

オブジェクトの種類 mygroup enegroup
1 4
敵攻撃 2 -
自機 4 3(=1+2)
自機攻撃 4 1

サンプル

test12.hsp :[2D/3D] オブジェクトの衝突・削除
physics_1.hsp :[3D/物理] 床とオブジェクトとの衝突判定

レンダリンググループ

20.レンダリンググループ設定 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#RENDERGRP )

 オブジェクト毎にカメラに映す/映さない、ライトの有効/無効を細かく設定できるようです。 サンプルで、pronama3.hspの次の行をコメントにすると雰囲気がつかめると思います。

setobjrender id_box, GRP_SKY

サンプル

pronama3.hsp :[3D] マルチパスによる鏡面反射レンダリング

物理挙動

21.物理挙動の設定 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#PHYSICS )

 hgimg4では、シーン内に配置されたオブジェクトに対して物理法則に従った挙動をさせることができます。 物理挙動の実装には、Bullet Physics Library ( https://pybullet.org/ )を使用しています。

物理挙動の対象は、次の通り。

  • 箱ノード(gpboxで生成)
  • 床ノード(gpfloorで生成)
  • 板ノード(gpplateで生成)
  • gpbモデルノード(gploadで生成)

 ヌルノードは対象とは書かれていませんね。大きさを持たないからダメなのかもしれませんね。

ノードに物理法則を適用するには

  • gppbind命令を適用すると物理法則に従う物体に設定できる。
  • 基本項目:重さ、摩擦係数、衝突のオプション
  • 衝突のオプション
    GPPBIND_NOSCALE :モデル全体を覆う球体を衝突判定に使う。負荷は軽い。
    GPPBIND_MESH :モデルのメッシュ形状を衝突判定に使う。負荷増大。
  • さらに詳細な設定は、gppset命令を使用する。
  • 物理法則を適用した物体は、setposなどの座標変更はできなくなる。
  • 動かすときは、gppapply命令で力を与える。
  • gppcontact, gppinfo, gppraytest で物理衝突情報を取得。

 ノードの挙動を物理エンジンにおまかせした後は、これまでのように場所を直接指定するような干渉はできなくなり、物理法則に従った干渉(力を与える)しかできなくなります。 あとは状態を観察(取得)する命令が用意されているので、その辺りを上手く使ってください。ということになります。

 物理の授業内容を忘れた方やまだ未受講の方には、ノードに物理的な力を適用する(gppapply)で書いてある説明がわかりにくいと思うので捕捉。

  • 瞬間的な衝撃 = ハンマーで叩き飛ばす
    指定した座標方向(ベクトル方向)に飛んでいきます。
  • トルク(ねじる)力 = 回転させる
    指定した座標方向(ベクトル方向)を中有心に回転します。右ねじ方向に回転します。

と理解しておけば大丈夫。後は動かしてみて値を調整すればいいだけです。

サンプル

physics_1.hsp, physics_2.hsp, test13.hsp

ノードの物理パラメーターを設定

gppset命令でノードのパラメータを設定できるのですが、よくわからない項目がたくさんあります。 おいおい確認していきたいですね。

GPPSET_ENABLE X=物理挙動のON/OFF(0=無効)
GPPSET_FRICTION X=摩擦係数, Y=弾力設定
GPPSET_DAMPING X=linear反発(0~1.0), Y=angular反発(0~1.0)
Damping…日本語にすると減衰とか制動。物理挙動を適用すると、調整によってはいつまでも振動して止まらない事があります。 この値を大きく設定すると早く静止するようになる…ということだと思います。
linear反発(リニアダンピング)
値が 1.0 のときは、移動に適用された力が一番弱くなる設定です。
angular反発(角度ダンピング)
値が 1.0 のときは、回転に適用された力が一番弱くなる設定です。
参考資料:https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2016/JPN/Maya/files/GUID-F7CD10A1-47D0-45A0-9E9A-495DF9F49B94-htm.html
GPPSET_KINEMATIC X=Kinematic設定のON/OFF(0=無効)
Kinematic剛体
質量はゼロで、ユーザーが動かすことができるオブジェクト。 オブジェクトを押したりすることはできるが、オブジェクトからは影響を受けない。
GPPSET_ANISOTROPIC_FRICTION X,Y,Z=異方性の摩擦
GPPSET_GRAVITY X,Y,Z=重力
重力加速度?単位は m/s^2 だと思います。オブジェクトごとに設定できるのは変な話ですね。
GPPSET_LINEAR_FACTOR X,Y,Z=ベクトルに沿った移動の設定
移動制限?
GPPSET_ANGULAR_FACTOR X,Y,Z=ベクトルに沿った回転の設定
移動制限?
GPPSET_ANGULAR_VELOCITY X,Y,Z=回転ベロシティー
速度
GPPSET_LINEAR_VELOCITY X,Y,Z=リニアベロシティー
速度
GPPSET_MASS_CENTER X,Y,Z=中心座標のオフセット

マテリアルの設定

22.マテリアルの設定 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#MATERIAL )

 描画に関する詳細な設定。色関連、テクスチャ、シェーダーの設定などがこの項目です。 見た目に直結する項目ですが、デフォルト設定のままでも支障がない部分です。

シーンの描画

26.シーンの描画について - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#SCENE )

 シーン内のオブジェクトの描画は、gpdraw命令で行います。 通常は引数なしで1回だけ実行れば十分です。

 描画の順番を変えたり、シーン描画の間にgcopy命令など別な描画命令をはさみたい場合は、引数を付けてgpdraw命令を実行する必要があります。 いくつか注意点として次のようなものが考えられます。

  • 最初のgpdrawには、GPDRAW_OPT_OBJUPDATEを付ける。
  • GPDRAW_OPT_DRAWSCENE_LATEは、GPDRAW_OPT_DRAWSCENEの後に描画する。
  • GPDRAW_OPT_DRAW2D_LATEは、GPDRAW_OPT_DRAW2Dの後に描画する。

半透明オブジェクト(_LATE)の描画は、不透明オブジェクトを描画した後にしないと半透明が反映されません。 なお、半透明はsetalpha命令で設定できます。

サンプル

physics_1.hsp

オブジェクトのコアパラメーター

 HGIMG4がオブジェクト毎に運用しているパラメータを取得/一部書き換えができます。 (gpsetprm, gpgetprm 命令)

 ユーザー独自の設定値も1つぐらい持たせられると便利な気がするのですが、そこは自分で管理しないとダメなようです。

実数ベクトルサポート命令

30.実数ベクトルサポート命令 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#VECTOR )

FV値:XYZ3つの値を格納した配列変数。実態はただの4要素の配列変数です。
FV値変数名(0) = X
FV値変数名(1) = Y
FV値変数名(2) = Z
FV値変数名(3) ← 謎の値

 FV値を使うと3回も同じことを書かなくていいので、楽に記述できます。 計算するときは、FV値同士を直接指定できないのでこんな感じで指定するといいと思います。

fvset fv1, 1, 0, 0
fvset fv2, 2, 0, 0
fvadd fv1, fv2(0), fv2(1), fv2(2)

 さらにstr2fvなどの便利な命令もあるので便利そうですね。 sel系命令で対象を選択後、obj~fv系命令でX,Y,Zの値をまとめて操作というような使い方もあるみたいです。

XYZの回転順番について

31.XYZの回転順番について - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#ROTORDER )

getang, getangr命令を使用すると、現在のオブジェクトの姿勢(傾き具合)をXYZの回転角度で取得できます。 ここまではなんとなく理解できても、この先は読んでも「だからどうした?」という感想になると思います。ということで補足説明。

取得した値を使ってオブジェクトをsetang命令(X軸→Y軸→Z軸)で回転させた場合と、setangy命令(Y軸→X軸→Z軸)で回転させた場合では、同じ向きになりません。 回転角で向きを指定する場合、X,Y,Z軸を同時に回転させるのではなく各軸方向に順番に1つずつ回転させます。 回転させる軸の順番を変えると、同じ角度であっても最終的な姿勢は全く異なってしまいます。

このためHGIMG4では複数の回転順番のパターンが用意されています。

レンダリングバッファ

35.レンダリングバッファ - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#RENDERBUFFER )

 表示されないウィンドウ(buffer命令)にレンダリング(カメラ映像を投影)した画像を利用する方法が、HGIMG4で使用できます。 HSP3Dishだと描画命令が使えなかったはずですが、HGIMG4ではこの制約がないようです。 ただし、html5/iOSでは現バージョン(HSP3.6)では対応していないので注意。

サンプル

buffer.hsp
feedback.hsp
tamane3.hsp

イベントリスト

 オブジェクトに対してイベントリストの適用が行われると、予め作成しておいたイベントリストに従ってオブジェクトが動作します。 敵の単純な動きやリアクションを設定しておくと管理がしやすそうです。例えば、アイテムのコインを拾うと回転しながら上に飛んでいって消えるとかでしょうか。

「イベントリストの作成」
newevent命令で新しいイベントIDを取得し、event_系命令でイベントリストにイベント(動作)を追加して作成します。 爆発やミサイルの軌道など定形動作を設定できます。待機やgotoのような命令もあるのである程度複雑な動作も指定できるようです。

「イベントリストの適用」
setevent命令で作成したイベントを実行する。 ただし、イベントの発火(検出、発生)は自分で判定する必要があります。

サンプル

light_test5eff.hsp
particle.hsp
physics_1.hsp
physics_2.hsp

階層情報の取得

39.階層情報の取得 - HGIMG4プログラミングガイド ( https://www.onionsoft.net/hsp/v36/doclib/hgimg4.html#NODEINFO )

 人形などの3Dモデルには、動きを設定するためのボーン(スケルトン)が設定されています。 このボーンは親子関係など複雑な階層(ノード、ツリー構造)を持っています。 各階層の情報は、gpnodeinfo命令で取得しノードと同様にアクセスすることができます。

 上手に使えば、手に物を持たせるような使い方ができるようになります。

サンプル

tamane_tree.hsp