HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2024
0901
アキアキノヒロロ[hgimg4/tamane_face.hsp] の [gpnodeinfo][gpmatprmt] に関して11解決


アキアキノヒロロ

リンク

2024/9/1(Sun) 11:12:18|NO.102114

サンプル [hgimg4/tamane_face.hsp] の [gpnodeinfo][gpmatprmt] に関してです。

[gpmatprmt] の "name"パラメーターを省略しても大丈夫なのは、ヘルプの解説で分かりました。

一方、[gpnodeinfo] の objidパラメーターを省略した場合についてです。

objidパラメーターが省略されていても、
[gpnodeinfo] の "name"パラメーター(階層ノード名)に指定されたものが、
gpload命令で読み込まれた3Dモデルのなかに一致するモデルがあるか、全てのモデルにあたって探していくようです。
探し当てた時、そのモデルが対象になって、書き換えが行われるようです。

objid が指定されていても、その objid のモデルに、指定階層ノード名がなければ、
次のモデル、次のモデルと探して行くようです。前のモデルへとは探さないようです。
そうやって次々探して行って、最初に見つけたモデルで書き換えが行われるようです。
見つからなければ、エラーになります。

こういうふうに理解しましたが、これで合っているでしょうか。
もちろん、objidパラメーターを指定して使うのが、本来のありかたで、省略などしないはずですが、
たまたま、色々とやっていた時にこのようなことに出くわしましたので。

あまり有益な事柄でもないので、スレッドの『種類』は『質問』とはしませんが、気になりました。



この記事に返信する


アキアキノヒロロ

リンク

2024/9/1(Sun) 19:51:54|NO.102118

サンプル [hgimg4/tamane_face.hsp] を書き換えて、実験してみたスクリプトです。

[repeat]ボタンを押すと、ランダムの順番で、3Dモデルたちを読込みます。
かつ、3Dモデルのどれかをランダムで、書き換え対象とします。(=ID)
[FACE1,2,3]ボタンで、書き換え実行です。
書き換え対象の『ID』と実際に書き換えられた3Dモデルが、合っていたり、いなかったり。
はて?

#include "hgimg4.as" chdir dir_exe+"\\sample\\hgimg4" randomize *go_repeat gpreset screen 0,700,480,, 100,100 setcls CLSMODE_SOLID, $808080 setcolor GPOBJ_LIGHT, 1,1,1 ; ライトカラーを設定 setdir GPOBJ_LIGHT, 0.5,0.5,0.5 ; アンビエントカラーを設定 ; ボタンを設置 objsize 100,30 button goto "repeat",*go_repeat // objsize 200,60 button gosub "FACE1",*face1 button gosub "FACE2",*face2 button gosub "FACE3",*face3 junban=rnd(4) if junban=0 : gosub *duck_L : gosub *duck_R : gosub *tamane2 : gosub *tamane2_R : gosub *tamane2_L if junban=1 : gosub *duck_R : gosub *tamane2_L : gosub *tamane2 : gosub *duck_L : gosub *tamane2_R if junban=2 : gosub *tamane2_L : gosub *duck_L : gosub *duck_R : gosub *tamane2_R : gosub *tamane2 if junban=3 : gosub *tamane2_R : gosub *duck_R : gosub *duck_L : gosub *tamane2_L : gosub *tamane2 goto *CAMERA *duck_L gpload id_duck_L,"res/duck" ; モデル読み込み setscale id_duck_L, 3,3,3 addpos id_duck_L, -5,0,0 return *duck_R gpload id_duck_R,"res/duck" ; モデル読み込み setscale id_duck_R, 3,3,3 addpos id_duck_R, 5,0,0 return *tamane2 gpload id_tamane2,"res/tamane2" ; モデル読み込み setscale id_tamane2, 0.1,0.1,0.1 addpos id_tamane2, 0,0,0 return *tamane2_L gpload id_tamane2_L,"res/tamane2" ; モデル読み込み setscale id_tamane2_L, 0.1,0.1,0.1 addpos id_tamane2_L, -10,0,0 return *tamane2_R gpload id_tamane2_R,"res/tamane2" ; モデル読み込み setscale id_tamane2_R, 0.1,0.1,0.1 addpos id_tamane2_R, 10,0,0 return *CAMERA setpos GPOBJ_CAMERA, 0,20,40 ; カメラ位置を設定 // gpact id_tamane2 nodename = "atama" ; テクスチャを入れ替えるノード名 ; 特定のノードに割り当てられたマテリアルを取り出す id=rnd(6) gpnodeinfo id_proxymat,id, GPNODEINFO_MATERIAL, "atama" repeat title "id_duck_L= "+id_duck_L+" id_duck_R= "+id_duck_R+" id_tamane2_L= "+id_tamane2_L+" id_tamane2= "+id_tamane2+" d_tamane2_R= "+id_tamane2_R stick key,15 if key&128 : end redraw 0 ; 描画開始 gplookat GPOBJ_CAMERA, 0,11,0 ; カメラから指定した座標を見る gpdraw ; シーンの描画 font "",20,1 : color 0,255,0 pos 110,70 : mes "id_tamane2_L= "+id_tamane2_L, mesopt_outline pos 270,40 : mes "id_tamane2= "+id_tamane2, mesopt_outline pos 430,70 : mes "id_tamane2_R= "+id_tamane2_R, mesopt_outline pos 210,380 : mes "id_duck_L= "+id_duck_L, mesopt_outline pos 370,380 : mes "id_duck_R= "+id_duck_R, mesopt_outline pos 30,410 : color 255,255,255 mes "ID = "+id mes "gpnodeinfo id_proxymat, ID, GPNODEINFO_MATERIAL, ''atama''" redraw 1 ; 描画終了 await 1000/60 ; 待ち時間 loop *face1 gpmatprmt id_proxymat, , "res/head_SD.png" return *face2 gpmatprmt id_proxymat, , "res/head_SD1.png" return *face3 gpmatprmt id_proxymat, , "res/head_SD2.png" return



アキアキノヒロロ

リンク

2024/9/3(Tue) 17:30:29|NO.102141

[gpnodeinfo] の objidパラメーターをランダムした場合のテスト動画、
X(旧ツイッター)に載せました。

https://twitter.com/akiakinohiroro/status/1830885471788114217



youdai

リンク

2024/9/7(Sat) 14:47:47|NO.102172

当現象の件を検証しました。

アキアキノヒロロさんのスクリプトは以下のような状態でした。

・gpnodeinfoの対象ノード名が間違っているケースがある
 duckの場合、正しくは"duck"が対象ノード名となる

・gpmatprmtの対象にすべきでないノードに対して命令を出しているケースがある
 このスクリプトの場合、オブジェクトのライトやカメラに対してまでgpmatprmtを使っているケースがある
 例えば、この場合0〜1のIDがそれに該当する

上記の結果、gpmatprmtが誤作動を起こしている、というのが当現象の理由です。
正しくgpmatprmtを使用すれば当現象は起きませんでした。



アキアキノヒロロ

リンク

2024/9/8(Sun) 12:52:12|NO.102178

youdai さん、検証ありがとうございます。

仰るように、「正しくgpmatprmtを使用すれば当現象は起きません」というのは分かりますし、
当然なことです。

ただ、何故、このスクリプトのように誤作動が生じても、エラーにならず、
3Dモデルを次々と当たっていき、対象ノード名のあるモデルに行き着いた時、
そのモデルの、ノードのマテリアルID(GPNODEINFO_MATERIAL)を取得することになるのか、
そのような流れが生じるのは、「誤作動」ではあっても、
そして書き換え指定したモデルではないにしても、対象ノード名のあるモデルが別にあれば、
そのモデルの書き換え自体は、出来てしまい、エラーにならない。
エラーになるのは、書き換え指定した[ID]以降のモデル全てに、
対象ノード名が見当たらない場合だけです。
「オブジェクトのライトやカメラに対してまでgpmatprmtを使って」も、エラーになりません。

当てずっぽうの素人感覚で言うと、[gpnodeinfo] で、3Dモデルの階層情報を取得するということは、
様々な階層情報が取得可能だが、そのうちのどの情報を取得するのかを [option] で指定するので、
全ての階層にあたりを付けざるを得ず、その延長として、求める情報が見つかるまで、
その指定した[ID]のモデルだけでなく、以降のモデルにまで、範囲を広げて行ってしまうのか。
でなければ、ここに生じているような「誤作動」は起こるはずがないのだから。

こんな風に勝手なことを考えてしまいます。
でも、何の役にも立ちそうもないですね。



youdai

リンク

2024/9/8(Sun) 18:40:22|NO.102182

>ただ、何故、このスクリプトのように誤作動が生じても、エラーにならず、

これは憶測なのでコメントには書かなかったのですが、この件についてエラーメッセージが出ない理由は単にエラーコードが設定されていないからだと思います。
エラーコードが設定されていない理由は、あえて間違って使わないと起こらない現象だからだと思います。

>そして書き換え指定したモデルではないにしても、対象ノード名のあるモデルが別にあれば、そのモデルの書き換え自体は、出来てしまい、エラーにならない。

正しいuniform名は忘れましたが、確かu_deffuseTextureに対して強制的に書き換え命令を送っているからだと思います。
アキアキノヒロロさんのスクリプトの場合、tamane2のu_deffuseTextureに送ってしまっているんだと思います。



アキアキノヒロロ

リンク

2024/9/9(Mon) 12:53:37|NO.102185

>エラーメッセージが出ない理由は単にエラーコードが設定されていないから

その通りだと思ってもいました。
試しに、[onerror] を使ってみました。

(1)
gpnodeinfo id_proxymat,id, GPNODEINFO_MATERIAL, nodename
onerror goto *mes_error *mes_error dialog "エラー",1 end
とした時、エラーとなるのは、[id]以降に[nodename]がない時だけです。
[id]を含めて[id]以降に[nodename]があれば、[id_proxymat] には、必ず正の値が入ります。

(2)
gpmatprmt id_proxymat, , "filename" 
onerror goto *mes_error *mes_error dialog "エラー",1 end
(1)のエラー判定をせずに、(2)とした場合、この部分でエラーとなる時は、[goto *mes_error] とはならず、
「*Error 3 in line __ (tamane_face.hsp)-->パラメータの値が異常です」
となるので、ここにはエラーコードが設定されているのが分かります。
この時の [id_proxymat] には、[-1] が入っています。


>強制的に書き換え命令を送っている

では、何故「強制的に書き換え命令を送って」しまうのか、ということが、私の一番の疑問なのです。
gpmatprmt id_proxymat, , "filename"
した時の [id] は、指定対象にすべきではないものが入っていても、例えば、[id=0] であっても、
それ以降の [id]に [nodename]があれば、[id=0] を無視して、[nodename]のあるモデル[id]に対して
「強制的に書き換え」をしてしまいます。
実際上、こういうことが起こる、....、可能なのは、何故なのか、ということです。
[id=0] であっても、「tamane2のu_deffuseTextureに送ってしまっている」ということが、
何故起こるのか、という疑問です。


私の疑問、上手く説明できているか、自信がありませんが。



アキアキノヒロロ

リンク

2024/9/10(Tue) 11:00:18|NO.102188

追加の疑問です。

サンプルの [hgimg4/tamane_face.hsp]
[gpnodeinfo] の [id_proxymat] を当たってみると、

id_proxymat=2097152

が入っています。
この値は、私が書き換えて、実験してみたスクリプトでも、
エラーになって、[stat=-1] で、[id_proxymat=-1] となった時以外は、いつも全く同じく

id_proxymat=2097152

が入ります。
[nodename = "atama"] を、[nodename = "duck"] としても、同じ値が入っています。
これらはどうしてなのか、どういう意味なのか。[2097152] とは、何なのか。
同じ値の [2097152] であっても、違うモデルのテクスチャを書き換えるのが、分かりません。



buhio

リンク

2024/9/10(Tue) 12:18:39|NO.102189

>追加の疑問です

実際のところはよくわかりませんが、
 gpnodeinfoで取得できるidは、ポインタなのかわかりませんが、gpnodeinfoを実行するたびに更新されてしまいますので、
オブジェクトidを変数に保存しておくことができないようです。
 この点は、おにたまさんに報告してマニュアルにも追記いただきました。
これが質問に関連しているかはわかりませんが、参考まで。

gpnodeinfoマニュアルより
(このオブジェクトIDは、gpnodeinfo命令で取得した直後しか使用できません。他の階層をgpnodeinfo命令で取得した場合は、以前に取得したオブジェクトIDは無効になります)



アキアキノヒロロ

リンク

2024/9/10(Tue) 13:52:39|NO.102190

buhio さん、レス有難うございます。

(このオブジェクトIDは、gpnodeinfo命令で取得した直後しか使用できません。
他の階層をgpnodeinfo命令で取得した場合は、以前に取得したオブジェクトIDは無効になります)

ヘルプにあった、この部分の具体的な意味がよく分からないでいたので、
このことが関係しているんだろうと、想像はしていましたが。

「gpnodeinfoを実行するたびに更新されてしまいます」といっても、
スクリプト上では、1度しか実行していないように見えるのですが、
1度書くだけで、他の階層をも取得するために、何度も実行されてしまうのでしょうか。
また、どんなモデルに対しても、どんなnodenameに対しても、必ず

id_proxymat=2097152

となるのも、分からないのです。

サンプルの [hgimg4/tamane_tree.hsp] に使われている [common / mod_gputil.as] が
関係しているのかとも、思いましたが、私の手には負えません。



usagi

リンク

2024/9/10(Tue) 21:57:22|NO.102191

>id_proxymat=2097152 の謎について

こんにちわ。以前お話ししたかもしれませんが、
HSPの内部的な実装の疑問はOpenHspを見てみるのがよろしいかと思います。
(実験しても分かりようが無いので。。。)
アキアキノヒロロさん程の能力があれば読み解けるはず!!

まず命令を調べる為、hsp3gr_dish.cpp を見る。

case 0x159: // gpnodeinfo res = game->getNodeInfo(p1, p2, ps, &vdata);

getNodeInfoを調べる為、gamehsp.cpp を見る

int gamehsp::getNodeInfo(int objid, int option, char* name, int *result) { int res = 0; Model* model; Drawable* drawable; Node* node = getNodeFromName(objid, name); if (node == NULL) { *result = -1; return -1; } if (option & GPNODEINFO_MATERIAL) { int matindex = option & (0x7f); *result = makeNewMatFromObj(objid, matindex, name); return res; }

ぱっと見ですが関数の戻り値としてはノードが無ければ-1、問題なければ0を返します。
そしてgpnodeinfo の var の値には *resultが返りましてその値はmakeNewMatFromObjによるものですね。
それは、gpmat.cppなどを見えれば良いですが長くなるので端折ると結局は"マテリアルのid"を返すようです。

2097152は16進数にすると0x200000とフラグに使っているようですね。
hgimg4.asを見てみてください
#const global GPOBJ_ID_MATFLAG (0x200000)
と定義されており、これでオブジェクトの種類がマテリアルかどうかの判定に使ってるのが分かりますね。
内部的に命令を実行するたびにaddMatという命令でマテリアルが作成されます。
おそらく必要な時に生成してメモリ効率を良く、無駄なくしているですね。

// addMatの一部抜粋 i がカウントされていく。 i|GPOBJ_ID_MATFLAG
つまり以下の様になっており、&&をとればマテリアルが判定できる訳です。
2097152(0x200000):1番目のマテリアル
2097153(0x200001):2番目のマテリアル
2097154(0x200002):3番目のマテルアル

長くなってしまうので、後は気が向いたらご自分でもOpenHSPを読んでみて欲しいですが、
nameが無い時はどう処理しているかも分かると思いますよ。

サンプルの [hgimg4/tamane_face.hsp]無駄に3回実行してみてください。
id_proxymat=2097154 になります。マテリアルへの参照IDが3つ生成されるわけですね。

gpnodeinfo id_proxymat,id_model, GPNODEINFO_MATERIAL, nodename gpnodeinfo id_proxymat,id_model, GPNODEINFO_MATERIAL, nodename gpnodeinfo id_proxymat,id_model, GPNODEINFO_MATERIAL, nodename

それでは失礼いたしました。



アキアキノヒロロ

リンク

2024/9/15(Sun) 14:08:51|NO.102214

usagi さん、いつも有難うございます。ご返答が遅れて、すいませんでした。

夏バテで頭が重く、不眠になって脳が働きません。

元々、基礎知識もなく、頭が悪い私が、OpenHsp に首を突っ込むのは、無謀な企みと、
承知しておりましたので、その名を聞いただけで、怖気づいてしまうのですが、
体調が戻ったら、覗いてみようと思います。

ということで、私としては、このスレはここで長期休眠(=終了扱い)と致します。

この、私の何気ない、ちょっとした疑問が、HSPの内部的な実装の問題に関わっているとは。



記事削除

記事NO.パスワード
(質問が解決したスレッドは他の利用者に活用してもらうため、削除しないようお願いします)

NO.102114への返信

マスコット

好きなマスコットを選んでください。

名前

e-mail
HOME
  1. 初めて利用する方は、HSP3掲示板の使い方をお読みください。
  2. 不要部分の多い長いスクリプトの投稿は ご遠慮ください。
  3. 書き込みは自動改行されません。適度に改行を入れてください。
  4. スクリプトは小文字の<pre>〜</pre>で囲むと見やすく表示できます。

削除用パスワード

エラー発生時、再送信すると二重送信になることがあります。
回答が得られたら、お礼書き込み時に[解決]チェックしてください。
SPAM防止のためURLから始まる文章は投稿できません。
SPAM防止のため英文字のみの本文を投稿することはできません。

ONION software Copyright 1997-2023(c) All rights reserved.