|
|
2022/2/7(Mon) 00:15:22|NO.95343
HGIMG4においてノードオブジェクトの親子関係の設定はできるでしょうか(HGIMG3のobjchild命令みたいに)。
HGIMG3からHGIMG4に乗り換え四苦八苦中です。
表裏のある板オブジェクトの管理で、うまく表と裏を一緒に管理したいのですが…
よい方法あったら教えて頂けると助かります m(_ _)m
|
|
2022/2/13(Sun) 08:47:05|NO.95403
>表と裏を一緒に管理
というのが、どういうことを意味するのか、よく分かりませんが、
「メタセコ」の場合、1つのモデルとして作っているのであれば、
板の表オブジェクトと、裏オブジェクト別々のまま出力しても、
あるいは、表と裏のオブジェクトを1つに合成して出力しても、
結局1つのモデルなので、できた[mqo]ファイルを[gpb]ファイルにして、読み込めばいいだけでは。
[gpb]ファイルへの変換は、ウサギさんの「mqo2gpb」で。
HSP物置 - JPN takeshima
https://z9z.sakura.ne.jp/box/hsp/
「ブレンダー」の場合、メッシュ追加で、表用平面メッシュと裏用平面メッシュを作って、
シェーディングで各メッシュのマテリアルを編集後、[fbx]ファイル出力し、
HSP付属の「GPB」コンバーターで変換して、読み込み。
「メタセコ」でも「ブレンダー」でも、1つのモデルとして作っていれば、それでいいのではないですか。
|
|
2022/2/14(Mon) 08:27:57|NO.95411
メッシュの表と裏で異なるマテリアルを指定したい場合、以下の手順で実装が可能です。
HGIMG4側でペアレント(親子関係づけ)する必要はありません。1つのGPBファイルとして出力できます。
モデリングで使用しているツールがblenderであること前提で説明します。
基本的な部分はアキアキノヒロロさんのアドバイスと同じですので、補足として書きます。
この方法は、実際には2枚のメッシュを使用して裏表で異なるマテリアルを実装します。
1.表裏で異なるマテリアルを指定したい部分のメッシュを複製する。
この作業はオブジェクトモードではなく、エディットモードで行う。
2.複製したメッシュの法線を反転する。
このメッシュは裏側のメッシュということになる。
3.裏側担当のメッシュに異なるマテリアルを指定する。
4.そのままFBXとして出力し、GPBコンバートする。
5.表と裏のマテリアルについて記述してある.materiarのrenderStateを以下のように変更する。
(以下の部分が同じであれば、変更する必要はない)
renderState
{
cullFace = true
depthTest = true
}
「cullFace = true」というのは、裏面を非表示する機能をオンにするという命令文です。
原理としては、裏面を非表示した部分に法線を反転したメッシュをあてることで、裏面に異なるマテリアルを表示する、という手法です。
これだけで表裏で異なるマテリアルを指定できます。
ちなみに、cullFaceはHSP3.7beta1ではデフォルトでtrueとして出力されるようです。
|
|
2022/2/21(Mon) 01:28:43|NO.95507
>HGIMG4においてノードオブジェクトの親子関係の設定はできるでしょうか
>(HGIMG3のobjchild命令みたいに)。
「HGIMG4プログラミングガイド」をもう一度、見返していたら、
「39.階層情報の取得」の項目がありました。
>gpnodeinfo var,objid,option,"name"
これの解説を繰返し読んで、何とか、理解したつもりですが、その具体的利用方法が考えつきません。
ここにのっている方法で、getpos、getang、getquat、できるようになるのは、分かりました。
これが私のスレ『[hging4] 列車用の物理挙動用ノードについて』の初めに紹介した、
〓hashikemu さん〓がおっしゃる、[gpload]したノードの[getpos]が可能になる方法につながるのだろう、
と、適当に(?)解釈しています。これは、とても有益な具体的利用方法の一つでしょう。
ただ、ノードの階層(親子関係)は、確かに取得できましたが、それは、具体的には、どのような時にどのようにすれば、
どのようなことができるようになるのか、利用方法が分かりません。
|
|
2022/2/21(Mon) 18:24:43|NO.95524
ひつじさんの言う「親子関係の設定」とは違う方向の話になってしまうかもしれませんが、
お許し下さい。もしかしたら、参考になるかも....。
一つだけ、思いつきました。
例えば、[sample\hgimg4\tamane_tree.hsp] で、
[nodename = "ude_L_"]
のようにすれば、腕の位置が取得でき、そこに何かを表示することで、
その何かを腕に持たせることができるはずだと。
ただし、この[tamane_tree.hsp] で、カメラ位置を動かすと、
[id_box] が、[nodename = "asi_L_"]の足の位置になっていない位置に
ずれてしまうように見えます。
これでは、意味をなさない。どうしてでしょう?
どこか、間違っているのでしょうか?
対処法があるのでしょうか?
|
|
2022/2/21(Mon) 20:59:29|NO.95527
もう一つ、です。
「HGIMG4プログラミングガイド / 39.階層情報の取得」の
>gpnodeinfo var,objid,option,"name"
ですが、これは、親子関係など複雑な階層(ノード)の情報を取得して
アクセス可能にする命令ということで、
youdai さんの
https://hsp.tv/play/pforum.php?mode=all&num=92411
での要望に対する、ある意味、答えがここにありそうな。
|
|
2022/2/24(Thu) 21:09:44|NO.95575
アキアキノヒロロさんやyoudaiさんの回答ですでに要件は満たしている気もしますが、
私の使っている方法を載せます。
まず、objchildのように自動で位置を更新してくれる方法はHGIMG4には無いので、
手動で更新する必要があります。
私の方法では、クォータニオン積というもので親子の位置関係を計算しています。
この方法のメリットとして、カスタムマテリアルが使える点があるかと思います。
また、アキアキノヒロロさんが言及されているgpnodeinfoですが、この命令で取得できる
ノードに対して位置姿勢を取得したとき、
位置(pos)はビュー座標系かつモデルの位置と姿勢が0、スケールが1の時の位置として、
姿勢(quat)は各ボーンの親ボーンに対するローカル姿勢として、
それぞれ取得されてしまうため、座標変換が必要になります。
とんでもなく長くて申し訳ないですが、以下のスクリプトで
親子関係づけ、ボーン姿勢取得の2つが実現できます。
#include "hgimg4.as"
#module mod_quat
#deffunc quatmul array p, array q, array qr
; クォータニオン積
ddim qr,4
qr(0) = q(3)*p(0)-q(2)*p(1)+q(1)*p(2)+q(0)*p(3)
qr(1) = q(2)*p(0)+q(3)*p(1)-q(0)*p(2)+q(1)*p(3)
qr(2) = -q(1)*p(0)+q(0)*p(1)+q(3)*p(2)+q(2)*p(3)
qr(3) = -q(0)*p(0)-q(1)*p(1)-q(2)*p(2)+q(3)*p(3)
return
#global
#module mod_hg4Util
; 数学座標系(東がX,北がY,上がZ)で扱うためのラッパー関数
#define global getposM(%1,%2,%3,%4) getpos %1,%2,%4,%3 : %3=-%3
#define global setposM(%1,%2,%3,%4) setpos %1,%2,%4,-(%3)
#define global getquatM(%1,%2,%3,%4,%5) getquat %1,%2,%4,%3,%5 : %3=-(%3)
#define global setquatM(%1,%2,%3,%4,%5) setquat %1,%2,%4,-(%3),%5
#define global getscaleM(%1,%2,%3,%4) getscale %1,%2,%4,%3
#global
#module "mod_0rGputil"
; ノードツリー情報を生成するモジュール(mod_gputilの改造版)
; 入力:モデルID
; 出力:ノード名配列、ノードネストレベル配列
#deffunc gptree_getsub str _nodeName, int _nestLevel, local childNodeName,array nameArray,array levelArray
nameArray(nodeCount)=_nodeName
levelArray(nodeCount)=_nestLevel
nodeCount++
childNodeName=""
; ルートノード名を取得
gpnodeinfo childNodeName,objid,GPNODEINFO_SKINROOT, _nodeName
if childNodeName!="" {
; ルートノードに子のノードが存在する場合に再帰呼び出し
gptree_getsub childNodeName,_nestLevel+1,nameArray,levelArray
}
childNodeName=""
; 子のノード名を取得
gpnodeinfo childNodeName,objid,GPNODEINFO_CHILD, _nodeName
repeat
if childNodeName="" : break
gptree_getsub childNodeName,_nestLevel+1,nameArray,levelArray
gpnodeinfo childNodeName,objid,GPNODEINFO_SIBLING, childNodeName
loop
return
#deffunc gptree_get array nameArray, array levelArray, int _objid
objid = _objid
sdim nameArray,0,1
dim levelArray,1
nodeCount = 0
gptree_getsub "",0,nameArray,levelArray
; デバッグ用に表示
repeat nodeCount
tmp=""
repeat levelArray(cnt)
tmp=tmp+" "
loop
; logmes tmp+nameArray(cnt)
loop
; ノードツリーの構造がきれいなので、探索対象ノードを見つけたら、その上方向にnodelevelがデクリメントするように探していけば親が見つけられる
return
#global
; スキンメッシュ補助モジュール
#module mod_skinnedMeshAux
; ツリー構造をもとにボーンのグローバル姿勢を取得する関数
#deffunc getSkinmeshBonePose array glbp, array qC, int obj_camera, int id_model, str _nodeName, array nameArray, array levelArray
; 特定ボーンにオブジェクトをアタッチするための関数
; 用途:アクションゲームの剣、銃をキャラクターに持たせる
nodeName=_nodeName
gpnodeinfo infonode,id_model, GPNODEINFO_NODE, nodeName
getposM infonode,x,y,z ; これはビュー座標系かつモデルの位置と姿勢が0の時の位置として出てきている
getscaleM id_model,sx,sy,sz ; さらにルートノードのスケールが1の時の位置として出てきている
; setpos infonode,0,0,0 ; これは動かない
; カメラの位置姿勢を取得
ddim p,3 : getposM obj_camera, p(0), p(1), p(2) ; 位置を取得 3x1ベクトル(縦ベクトル)
ddim q,4 : getquatM obj_camera, q(0), q(1), q(2), q(3) ; クォータニオンを取得 4x1ベクトル
ddim qConj,4 : qConj(0,0)= -q(0), -q(1), -q(2), q(3) ; 共役クォータニオンを求める(x,y,z成分をマイナスつける)
; ビュー座標系からワールド座標系に変換
ddim viwp,4 : viwp(0,0)= x,y,z,1.0
ddim qTmp,4 : quatmul qConj, viwp, qTmp
ddim glbp,4 : quatmul qTmp, q, glbp ; この座標にカメラ位置pを足すとモデルのルートの位置と姿勢が0の時のワールド座標になる
; モデルのルートの位置姿勢を取得
ddim pR,4 : getposM id_model, pR(0), pR(1), pR(2) ; 位置を取得
ddim qR,4 : getquatM id_model, qR(0), qR(1), qR(2), qR(3) ; クォータニオンを取得
ddim qRConj,4 : qRConj(0,0)=-qR(0),-qR(1),-qR(2), qR(3) ; 共役クォータニオンを求める(x,y,z成分をマイナスつける)
; モデル姿勢へ座標変換
ddim locp,4 : locp(0,0)= sx*(p(0)+glbp(0)),sy*(p(1)+glbp(1)),sz*(p(2)+glbp(2)),1.0
ddim qTmp,4 : quatmul qRConj, locp, qTmp
ddim glbp,4 : quatmul qTmp, qR, glbp
repeat 3 : glbp(cnt)+=pR(cnt) : loop
; 姿勢をノードツリーを使用して計算する
DBG_MSG_NODEINFO=""
nodeIdx=0
repeat length(levelArray)
if nameArray(cnt)==nodeName : nodeIdx=cnt : break
loop
ddim qN,4
ddim qC,4 : qC(0,0)=0.0,0.0,1.0,0.0
ddim qCNew,4 : qCNew(0,0)=0.0,0.0,1.0,0.0
repeat
; 名前と深さを取得
nodeName= nameArray(nodeIdx)
nodeLvl= levelArray(nodeIdx)
; デバッグ用に姿勢変換に使ったノードツリーを表示
repeat nodeLvl
DBG_MSG_NODEINFO+="_"
loop
DBG_MSG_NODEINFO+=nodeName+"\n"
; 名前のノードのquatを取得、qCに積算
gpnodeinfo infonode,id_model, GPNODEINFO_NODE, nodeName
getquatM infonode,qN(0),qN(1),qN(2),qN(3) ; quatもangもそのノードのローカル座標系で出力されるので、このように積算が必要
quatmul qC,qN,qCNew
repeat 4 : qC(cnt)=qCNew(cnt) : loop
; ノード深さが1になるまで繰り返し親ノードに移動
if nodeLvl<=1 : break
repeat
nodeIdx--
if levelArray(nodeIdx) < nodeLvl : break
loop
loop
; 最後にルートの姿勢を積算
quatmul qC, qR, qCNew
repeat 4 : qC(cnt)=qCNew(cnt) : loop
return
#global
gpreset
; モデルロード
gpload id_model,dir_exe+"/sample/hgimg4/res/tamane2",""
sc = 0.01 ; モデルのスケール
setscale id_model, sc, sc, sc
setpos id_model,1,0.5,1
setang id_model,0.4,0.1,0.1
gpact id_model
; モデル構造の取得
sdim nameArray,64,200
dim levelArray,200
gptree_get nameArray,levelArray,id_model
; 床の生成
gpfloor flr, 8,8, $00ffff ; 床
; アタッチする箱を生成
gpbox id_box, 0.2
; 親子付けするモデルをロード
gpload id_child,dir_exe+"/sample/hgimg4/res/tamane2",""
sc = 0.005 ; モデルのスケール
setscale id_child, sc, sc, sc
repeat
redraw 0
; カメラ
getreq tim,SYSREQ_TIMER
setpos GPOBJ_CAMERA,cos(0.0005*tim)*10,1,sin(0.0005*tim)*10
gplookat GPOBJ_CAMERA, 0,0,0
; モデルを回転
addang id_model,0.0,0.01,-0.005
; 箱をasi_L_にアタッチ
getSkinmeshBonePose pBone, qBone, GPOBJ_CAMERA, id_model, "asi_L_", nameArray, levelArray
setposM id_box,pBone(0),pBone(1),pBone(2)
setquatM id_box,qBone(0),qBone(1),qBone(2),qBone(3)
; 手動で親子付けする
; クォータニオン積を用いてローカル回転を計算
angA=-0.3
angB=0.01*tim
angC=0.1
ddim p,3 : getposM id_model,p(0),p(1),p(2)
ddim q,4 : getquatM id_model,q(0),q(1),q(2),q(3)
ddim qConj,4 : qConj(0,0)=-q(0),-q(1),-q(2),q(3) ; 共役クォータニオンを求める(x,y,z成分をマイナスつける)
ddim qA,4 : qA(0,0)=sin(0.5*angA), 0.0, 0.0, cos(0.5*angA)
ddim qB,4 : qB(0,0)=0.0, sin(0.5*angB), 0.0, cos(0.5*angB)
ddim qC,4 : qC(0,0)=0.0, 0.0, sin(0.5*angC), cos(0.5*angC)
ddim qCq,4 : quatmul qC,q,qCq
ddim qBqCq,4 : quatmul qB,qCq,qBqCq
ddim qAqBqCq,4 : quatmul qA,qBqCq,qAqBqCq
;(ローカル座標系で回されるので)qAqBqCq=qA*qB*qC*q (右側から計算していく 先にqCを適用することになる)
; クォータニオン積を用いてローカル移動を計算
locX=0.1
locY=0.1
locZ=2.0
ddim locP,4 : locP(0,0)=locX,locY,locZ, 1.0
ddim qTmp,4 : quatmul qConj, locP, qTmp
ddim trsLocGlb,4 : quatmul qTmp, q, trsLocGlb
setposM id_child, trsLocGlb(0)+p(0), trsLocGlb(1)+p(1), trsLocGlb(2)+p(2)
setquatM id_child, qAqBqCq(0), qAqBqCq(1), qAqBqCq(2), qAqBqCq(3)
; 描画
gpdraw
redraw 1
await 1000/60
loop
| |
|
2022/2/25(Fri) 07:13:11|NO.95576
hashikemu さん、ご返答頂き、本当に有難うございます。
ご無理を言って、申し訳ありませんでした。
ただ、今の私がこれを理解するのに、どれほどの時間がかかるかを思うと、頭を抱えてしまいます。
それでも、あれこれ書き換えて、試させて頂いているうちに、どうにか使い方だけは分かってきました。
なので、失礼ながら、自分なりに試したものを動画にしてみました。
https://twitter.com/akiakinohiroro/status/1496968618831396867
親子関係づけ、ボーン姿勢取得。
これが可能になったことで、また [hgimg4] に新たな広がりが生まれたように思います。
このスクリプト(モジュール)、時間がかかっても勉強して行きます。
hashikemu さん、有難うございました。
そして、ひつじさん、スレッドの横取り、すいません。
|
|
2022/3/7(Mon) 02:08:15|NO.95642
みなさん、たくさんコメントありがとうございます。
お返事遅くなってしまいごめんなさい。
質問が具体的でなかったですね汗
バッファーに描出した内容を使って、gpscrmatとgpplateで板ノードを作成し、
表裏のあるカードを作成するようなことを想定していました。
hashikemuさんの指摘のように、手動で管理することにしました。
質問とはずれてしまいますが、示して頂いたボーンへのオブジェクトアタッチは
かなり有用そうですね。
色々ありがとうございました。
|
|
2022/3/7(Mon) 06:28:06|NO.95643
ひつじさん
こんにちは。Dripです。横から失礼します。
>質問が具体的でなかったですね汗
>バッファーに描出した内容を使って、gpscrmatとgpplateで板ノードを作成し、
>表裏のあるカードを作成するようなことを想定していました。
>hashikemuさんの指摘のように、手動で管理することにしました。
やはりそういう意味でしたか…^^;
ご本人不在のようでしたので上のアドバイスで解決されたのかと思い閉口してしまったのですが…
objchild命令ってplateかboxにしか設定できなかったかと思いますので、
今回はモデルの話ではなくスクリプト中で生成されるポリゴンの両面化という趣旨でよろしかったのですね。
その意味で説明させていただきます。
Hgimg4で両面プレートを生成する方法は複数あります。
まずHgimg4ではHgimg3のようにパネルを合体させなくても両面ポリゴンが使用可能です。
まず単純に両面プレートを作成したいだけであれば gpplate で作成したパネルに対して
gpmatstate 命令で cullFace に false を与えてやりましょう。
#include "hgimg4.as" //Hgimg4読み込み
chdir dir_exe+"\\sample\\hgimg4" //サンプルフォルダの素材を使う
//パネルに角度が付いた際のテクスチャのライティングや簡素描画が不要な場合、
//次のコメントアウトしている箇所を任意で解除してみてください。
gptexmat mat,"res/qbox.png";,GPOBJ_MATOPT_NOLIGHT|GPOBJ_MATOPT_NOMIPMAP
gpplate id,10,10,,mat
gpmatstate id,"cullFace","false"
repeat
addang id,0,0.1
redraw 0
gpdraw
redraw 1
await 16
loop
次に、両面別のテクスチャを割り当てようとした場合、スクリプトだけで行うのであればフリーメッシュを使用する方法があります。
但し、この方法では2枚のテクスチャに対応できず、1枚のテクスチャに両面分のテクスチャを描いておく必要があります。
#include "hgimg4.as" //Hgimg4読み込み
chdir dir_exe+"\\sample\\hgimg4" //サンプルフォルダの素材を使う
//UVを登録するマクロ(p1=テクスチャサイズ,p2,p3=UV左上座標 p4,p5=UV右下座標)
#define setuv(%1,%2,%3,%4,%5) _uv_(_uvID_\2*4)=double(%2)/%1,1.0-double(%5)/%1,double(%4)/%1,1.0-double(%3)/%1:_uvID_++
//フリーメッシュでgpplateと同じ書き方で両面ポリゴンを生成するマクロ
#define gpplate2(%1,%2,%3,%4=$FFFFFF,%5=-1) gpmeshclear:repeat 8:gpmeshadd _p_(cnt),%2*(cnt\2)-%2/2,\
%3*(cnt/2\2)-%3/2,0,0,0,1-(cnt>=4)*2,_uv_(cnt/4*4+((cnt+(cnt>=4))\2*2)),_uv_(cnt/4*4+1+(cnt/2\2*2)):loop:\
gpmeshpolygon _p_(0),_p_(1),_p_(2),_p_(3):gpmeshpolygon _p_(5),_p_(4),_p_(7),_p_(6):gpmesh %1,%4,%5
//↑のマクロの使用サンプル
setuv 512, 128,64, 192,128 //表のUV(10と描かれたボール)(512はテクスチャサイズ)
setuv 512, 384,192, 448,256 //裏のUV(30と描かれたボール)
//パネルに角度が付いた際のテクスチャのライティングや簡素描画が不要な場合、
//次のコメントアウトしている箇所を任意で解除してみてください。
gptexmat mat,"res/ball64.png";,GPOBJ_MATOPT_NOLIGHT|GPOBJ_MATOPT_NOMIPMAP
gpplate2 id,10,10,,mat //両面ポリゴン作成!
repeat
addang id,0,0.1 //10と30の模様がくるくる回る
redraw 0
gpdraw
redraw 1
await 16
loop
しかしこの方法には1点問題があります。
gpmeshpolygonで指定すべきポリゴンの登録順序がマニュアルの仕様通りに指定した場合うまく動作しません。
マニュアルでは時計回りに登録と書いてありますが、実際は「逆Z型」に登録しなければならず、このメッシュ命令をどこまで信用して使用したら良いのかわからない状況です。
なので、万が一仕様に変更があった場合、すみやかに修正できるようにプログラムを整理して使用する必要があるように思います。
私のサンプルではsetuvのマクロ中、値を直接代入せず、変な加工をして代入しているのがわかるかと思います(テクスチャサイズ(1.0)から座標分を引いています)。これが今回色々仕様どおりに動かないための補正です。
またgpplate2のマクロ中、3行目のgpmeshpolygonで登録する順序もなんか少しおかしいのがわかります。これも仕様と異なる登録順序(逆Z型)に対応するためのものです。
マクロ化して利用する上では仕様変更への対応が楽ですが、スクリプト中あちこちでgpmeshpolygon命令を使用しているとやってられなくなるかと思います。
これらの部分は命令の動作を充分に把握し、私のマクロのコピペではなくご自分で筆記されることを強くお勧めします。
このほかにも、シェーダーを別途用意して対応するなど、色々な方法があるかと思いますが、入門ではまず標準機能だけで色々弄ってみたいですよね?f^−^;
今回はあくまでスクリプト中で両面ポリゴンを手軽に使用する方法を2例書いてみました。
参考にしていただければ幸いです。
| |
|