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


HSPTV!掲示板


未解決 解決 停止 削除要請

2024
0414
アキアキノヒロロ[getwork2]の取得値を角度値として利用できる?23解決


アキアキノヒロロ

リンク

2024/4/14(Sun) 13:13:08|NO.101521

[gppraytest]ヘルプの解説にあるように、[getwork]で得られた値は、衝突座標であり、
また、[getwork2]の取得値は、[getwork]の取得座標からの法線ベクトルであることも分かります。
ただ、この[getwork2]の取得値を角度値として利用できるのではないかとも思ってしまいます。

初心者同然の私は、「ベクトル」の概念と「角度」の概念の関係がよく理解できていないまま、
以前、この[getwork2]の取得値を角度のように勘違いしていました。
そして、今取り組んでいるゲームプログラムに角度値として利用応用したところ、
実際なんとかなって、出来てしまったからです。

具体的に言います。
「Y->X->Zの順番」設定の [setangy]でならば、そのY軸の向きでのX,Z軸回転の設定になるはずだから、
一旦、[getwork2] の値を、[setangy] で、その順番で設定します。

> getwork2 id_null, vector_x,vector_y,vector_z
> setangy obj_model, vector_x,vector_y,vector_z

こうやって回転させた後、[addang] で、Y軸だけその分 [ー] して元に戻してやります。

> addang obj_model, 0.0, -vector_y, 0.0

これで、「obj_model」には、X軸とZ軸だけの回転が残ります。そして、その上で、
[←,→]等のキー操作による「obj_model」の回転角度(Y_ang)をY軸に [+] してやるのです。

> addang obj_model, 0.0, (Y_ang), 0.0

こうすることで、デコボコな地面の、ある地点の前後左右の傾きを取得再現利用できてしまいました。
これが、デコボコ地面走行時の車の傾き再現になるのです。
試行錯誤の果てに、偶然(?)どうにかなったものなので、この方法が考えとしても合っているのか、
教えていただけないでしょうか。
出来れば、「ベクトル」と「角度」の概念から、説明して頂けると、ありがたいです。



この記事に返信する


アキアキノヒロロ

リンク

2024/4/14(Sun) 13:20:53|NO.101523

言い忘れました。

この[getwork2]は、真下向きの[id_null]で[gppraytest]したものです。



buhio

リンク

2024/4/15(Mon) 18:14:22|NO.101528

 こんにちわ

 詳しい数学のことは正直分かりません。

 法線ベクトルというのは、面の向いている方向を表すxyzで、角度ではなく、長さ1の矢印が指し示すワールドxyz座標だと認識しています。
 ポリゴンの面はあらゆる方向を向く可能性がありますが、長さ1(正規化)された座標なので、原点がゼロで、半径1の球体の表面を必ず示すxyz座標になるかなと。
 (違ったらすいません)

 正規化していないベクトルは、単なる座標を示す(というのは正しくないと思いますが、まぁいいや。)

 
 あるベクトルAとベクトルBの外積を計算する(fvouter)⇒AとBに直交するベクトルCが得られる(3つの値、xyzが得られる。)
 あるベクトルAとベクトルBの内積を計算する(fvinner)⇒ベクトルCを回転軸とした場合のAからBへの角度(1つの値θが得られる。)
 

 ----で、デコボコの地面の法線ベクトルにしたがって、モデルの角度を変更したい-----

 gppraytestで法線ベクトルを取得。
 
 ベクトルA(0,1,0);真上のベクトル(Y_UP)
 ベクトルB(法線ベクトル);raytestから取得

 AとBの外積 ベクトルCを得る。
 AとBの内積 角度θを得る

 ベクトルCという軸でθ度回転したクオータニオンQを得る(ユーザー関数)
 (私では、クオータニオンを使わずに任意軸回転が思いつきませんでした)

 クオータニオンQに元々のモデルのクオータニオンを乗算(ユーザー関数)

 結果をモデルにsetquatする。。。

 ----
 という手順で実現はできましたが、私にはクオータニオンのスクリプトがどうしても必要でした。
 このあたりの数学的説明はこれ以上できませんが、とりあえず可能です(説明になってないですね。すいません)
 HSPの標準命令だけで実現するには、どなたかのお知恵を拝借するしか。 
 参考程度になればいいのですが。

 https://youtu.be/fBMef3dQP_U
 (がくがく地面に影響を受けます。動画はいきなり角度が変わらないように補完しながら地面の角度を適用しています。


;============================================================================= ;クオータニオンの乗算 ;============================================================================= #deffunc QuatMul array _q3,double x,double y,double z,double w,double x2,double y2,double z2,double w2 q1(0)=x q1(1)=y q1(2)=z q1(3)=w q2(0)=x2 q2(1)=y2 q2(2)=z2 q2(3)=w2 _q3(0)=0.0f _q3(1)=0.0f _q3(2)=0.0f _q3(3)=0.0f _q3(3)= q1(3) * q2(3) - q1(0) * q2(0) - q1(1) * q2(1) - q1(2) * q2(2) _q3(0)= q1(1) * q2(2) - q1(2) * q2(1) + q1(3) * q2(0) + q1(0) * q2(3) _q3(1)= q1(2) * q2(0) - q1(0) * q2(2) + q1(3) * q2(1) + q1(1) * q2(3) _q3(2)= q1(0) * q2(1) - q1(1) * q2(0) + q1(3) * q2(2) + q1(2) * q2(3) return ;============================================================================= ;クオータニオンの軸回転(度数指定) ;============================================================================= #define PI 3.14159265358979 #deffunc QuatRotate array v,double r rad=0.0f s=0.0f rad = r * (PI / 180.0) / 2.0; s = sin(rad); ;logmes cos(rad) ;logmes v(3) v(0) = double(v(0)) * s v(1) = v(1) * s v(2) = v(2) * s v(3) = cos(rad) return



usagi

リンク

2024/4/15(Mon) 19:13:34|NO.101529

こんにちわ

>この方法が考えとしても合っているのか、教えていただけないでしょうか。

ご自身のプログラムで理想が満たされているのであれば問題無いと思いますが、
おそらく、傾斜がキツくなると満たされなくなるのではと思われます。
(たまたま、利用していた範囲でそれっぽく動いていた)

ベクトルと角度は違うものなので、使い方や考え方としては間違っていると思いました。

以前クォータニオンの回転を説明させていただきましたので、
そちらを使った方がよろしいかと思いました。
(やりたい事の理想がオイラー角で表現しやすい事を超えてきてますので)


#include "hspmath.as" #include "hgimg4.as" screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 ; カメラ setpos GPOBJ_CAMERA, 10,10,10 gplookat GPOBJ_CAMERA, 0,0,0 ; 軸 (右手座標 Y UP) gpbox id_axis_x, 0.1, $FF0000 : setpos id_axis_x, 5 : setscale id_axis_x, 100,1,1 gpbox id_axis_y, 0.1, $00FF00 : setpos id_axis_y, ,5 : setscale id_axis_y, 1,100,1 gpbox id_axis_z, 0.1, $0000FF : setpos id_axis_z, ,,5 : setscale id_axis_z, 1,1,100 ; 床 gpbox id_floor, 1, $00FFFF : setpos id_floor, 0,-1 : setscale id_floor, 10, 0.1, 10 ; ★ここを変えてみて★ setangr id_floor, 32, 0, 32 ;setangr id_floor, 64, 0,-16 ; ★★★★★★★★★★ gppbind id_floor, 0 ; モデル gpload id_model,"res/tamane2" setscale id_model, 0.01,0.01,0.01 ; 今回は床しかないので、カメラからキャスト(床の法線とれればよいので) gppraytest id, GPOBJ_CAMERA, 100 getwork2 GPOBJ_CAMERA, norm.0, norm.1, norm.2 ; 上方向ベクトルを用意 (単位ベクトル) fvset vec_up, 0.0, 1.0, 0.0 ; 上方向ベクトルと法線との外積を計算⇒軸を求める。(正規化済) fvset vec_axis, vec_up.0, vec_up.1, vec_up.2 fvouter vec_axis, norm.0, norm.1, norm.2 ; 上方向ベクトルと軸で内積を計算⇒cosθ、⇒逆関数で角度を求める fvset dot, vec_up.0, vec_up.1, vec_up.2 fvinner dot, norm.0, norm.1, norm.2 ang_rad = acos(dot.0) ; 軸と角度でクォータニオンをセットアップ half_theta = ang_rad / 2.0 : s = sin(half_theta) qua.0 = vec_axis.0 * s, vec_axis.1 * s, vec_axis.2 * s, cos(half_theta) ; モデルに設定 setquat id_model, qua.0, qua.1, qua.2, qua.3 ; ご提示された方法だと合わない。 ;setangy id_model, norm.0, norm.1, norm.2 ;addang id_model, 0.0, -norm.1, 0.0 redraw 0 ; 描画開始 gpdraw ; シーンの描画 color 255,255,255 : pos 0,0 mes strf("法線:%3.2f, %3.2f, %3.2f", norm.0, norm.1, norm.2) redraw 1 ; 描画終了



アキアキノヒロロ

リンク

2024/4/16(Tue) 05:15:45|NO.101533

buhioさん、usagiさん、いつもいつも、お世話になっております。
ご返答いただき、ありがとうございます。


>buhioさん
「ベクトル」と「角度」の概念、丁寧なご説明、とても助かりました。
高校の数学の授業、チンプンカンプンで、迷子のおいてけぼりだった身には、
相変わらず、「クォータニオン」と聞いただけで、拒絶反応を起こしてしまいますが......。


>usagiさん

>たまたま、利用していた範囲でそれっぽく動いていた
>ベクトルと角度は違うものなので、使い方や考え方としては間違っていると思いました。

その通りだと、自分でも理解していますが、それでも、何故それっぽくできてしまったのか、
偶然だとしても、偶然に思えない何かがあるように感じてしまいます。
その辺りが分かれば、少しはスッキリするのですが。


御二方には、本当に毎回、お力添え頂いて、助かっております。
70才、認知症に近づいている頭には、なかなかに厳しい内容ですが、
御二方のご提示くださったものを猛勉強しているところです。
解決とはせずに、少しお時間を頂きたいと思います。



usagi

リンク

2024/4/16(Tue) 12:40:10|NO.101534

ご理解されていたのですね。失礼いたしました。

>偶然だとしても、偶然に思えない何かがあるように感じてしまいます。

疑似相関みたいな事でしょうか。
上手くいった理由はどこかにあるのかもしれませんが、特定条件下だとは考えてます。

スクリプトを見ないと分かりませんが、おそらく。。。

法線方向が上なら[0,1,0]で、右なら[1,0,0]だと思いますが、
このままXZ平面上で90度回してみると方向ベクトル(単位ベクトル)の絶対値は1ですから
[1,0,0]⇒[0,0,1]⇒[-1,0,0]⇒[0,0,-1]⇒[1,0,0]
と循環します。

これって円運動ですよね。

角度はラジアンなので1は大体60度くらいになります。
平面に近づくと[0.7, 0.7, 0]ですがYは無視する作りなので、0.7radは40度くらい。
同じように完全に上だと[0,1,0]ですから0度ですよね。

取れる値として0〜60度くらいの範囲でその他スクリプト(試行錯誤)と上手い事かみ合って、
見かけ上、上手くいっているように見えたのではと思いました。

キャラクターの足元から頭までの”ベクトルと法線は本当に一致しているのか”
が気になりましたので、デバック表示してみると良いかと思いました。

スッキリしますかねぇ。。。

>デコボコ地面走行時の車の傾き再現
というわけで、どんな法線でも満たすのか確認してみて頂けると
偶然なのかどうか分かるかと思いました。

(たとえば法線[0,-1,0]の様な天井に忍者の様に立つ形を再現できるのか。)


>クォータニオン」と聞いただけで、
クォータニオンは道具として使うだけなら、中身の数学的理解はする必要は無いので、
"gpload"の中身を理解せず使うくらいな感じでチャレンジしてみても良いかもですね。
(とは言え敷居は高いかもですが現代3Dでは必須なので。。。)

逆に使わずに"ロドリゲスの回転公式"などで回転行列を求めてもいいかもしれませんが、
もっと拒絶反応を示すかもしれません。

難しい方法というより、より簡単な方法を提示しているつもりではあるのですが。。。
3Dは難しいですよね。

一番単純なのは法線に立つだけならモデルをZ軸ではなくY軸正面として作っておいて
法線方向に"gplookat"するのがシンプルかと思いました。

※クォータニオンの計算は中身で勝手におこなってくれますから見た目上スクリプトでの使用を回避できる
※XYZ軸のボーンの入ったダミーモデル用意して法線にgplookat,−Y軸にgplookatでもイケるかも?



buhio

リンク

2024/4/16(Tue) 13:09:07|NO.101535

素晴らしい検証スクリプトを拝見し、自分なりに師匠のスクリプトの計算結果と自分のスクリプトが合致するかテストしました。
一点、ヽ粟僂鬚箸辰織戰トルを一旦正規化すると、ぴたっと板に張り付きます。ここで違いがありました。

また、自分的に見やすく動きを付けてみました。

ワタクシもHSPから数学に戻ったクチですが、「文系でもわかる高校数学」など、ブタでもわかるように書いてくだすった本とにらめっこしたりしています。
クオータニオンに関しては、簡単な本というのが見つからないのですが、https://hakuhin.jp/as/quaternion.html#QUAT_03 というようなサイトのコードをHSPに移植してみたり、
いろんな方(GENKIさん・hashikemuさん)の書いたクオータニオンの命令を使ってみることで、仕組みはわからんでも、思った通りになんとか動くという感じまで来れました。
要は動けばいいわけで、そんなもんと思っております。
(数式は、半年くらい眺めてたらなんか見える時がある、、、)
標準のHGIMG4の命令だけでやるのは、私はもうしんどいです。クオータニオンとマトリックス計算をサポートして欲しい〜と思います。


#include "hspmath.as" #include "hgimg4.as" screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 ; カメラ setpos GPOBJ_CAMERA, 0,10,10 ;🐽変更 gplookat GPOBJ_CAMERA, 0,0,0 ; 軸 (右手座標 Y UP) gpbox id_axis_x, 0.1, $FF0000 : setpos id_axis_x, 5 : setscale id_axis_x, 100,1,1 gpbox id_axis_y, 0.1, $00FF00 : setpos id_axis_y, ,5 : setscale id_axis_y, 1,100,1 gpbox id_axis_z, 0.1, $0000FF : setpos id_axis_z, ,,5 : setscale id_axis_z, 1,1,100 ; 床 gpbox id_floor, 1, $00FFFF : setpos id_floor, 0,0 : setscale id_floor, 10, 0.1, 10 ; ★ここを変えてみて★ setangr id_floor, 0, 0, 0 ;🐽変更 ;setangr id_floor, 64, 0,-16 ; ★★★★★★★★★★ gppbind id_floor, 1  ;🐽重さ1に変更(重さが0だとKINEMATICが効かない) gppset id_floor,GPPSET_KINEMATIC,1;🐽追加(動かせるように) ; モデル gpload id_model,"res/tamane2" setscale id_model, 0.01,0.01,0.01 r=0.0f ;🐽追加 i=1.0f ;🐽追加 *main ;🐽追加 if r>1.4{i=-1}:if r<=-1.4{i=1}:r+=(0.01f*i):setang id_floor,0,0,r;🐽床の左右回転追加 ; 今回は床しかないので、カメラからキャスト(床の法線とれればよいので) gppraytest id, GPOBJ_CAMERA, 100 getwork2 GPOBJ_CAMERA, norm.0, norm.1, norm.2 ; 上方向ベクトルを用意 (単位ベクトル) fvset vec_up, 0.0, 1.0, 0.0 ; 上方向ベクトルと法線との外積を計算⇒軸を求める。(正規化済) fvset vec_axis, vec_up.0, vec_up.1, vec_up.2 fvouter vec_axis, norm.0, norm.1, norm.2 fvunit vec_axis ;←←🐽正規化追加(はずすと少し変わる) ; 上方向ベクトルと軸で内積を計算⇒cosθ、⇒逆関数で角度を求める fvset dot, vec_up.0, vec_up.1, vec_up.2 fvinner dot, norm.0, norm.1, norm.2 ang_rad = acos(dot.0) ; 軸と角度でクォータニオンをセットアップ half_theta = ang_rad / 2.0 : s = sin(half_theta) qua.0 = vec_axis.0 * s, vec_axis.1 * s, vec_axis.2 * s, cos(half_theta) ; モデルに設定 setquat id_model, qua.0, qua.1, qua.2, qua.3 ; ご提示された方法だと合わない。 ;setangy id_model, norm.0, norm.1, norm.2 ;addang id_model, 0.0, -norm.1, 0.0 redraw 0 ; 描画開始 gpdraw ; シーンの描画 color 255,255,255 : pos 0,0 mes strf("法線:%3.2f, %3.2f, %3.2f", norm.0, norm.1, norm.2) redraw 1; 描画終了 await 1000/60;🐽追加 goto *main;🐽追加



usagi

リンク

2024/4/16(Tue) 22:55:54|NO.101541

>buhioさん
わぁ、素晴らしい。動くととても見やすいですね。
正規化は入れ忘れてました。すみません。

サンプル実行の見栄えというものは意識しているのですが、
私のは直感的ではなかったですね。床を動かした事がとても良いと思いました。


>アキアキノヒロロさん
追加でgplookatでイケるかもと書きましたが、少し面倒そうですね。
オイラー角特有の向きが分からなくなってしまう問題(フリップ)も発生しますし、
場合分けなどで、かえって記載量も多くなってしまいあきらめました。

任意の軸(法線)で。。。という事を考えるとクォータニオンが一番楽かもしれません。
(それを簡単、回避にする為に導入された事もあると思いますので)

buhioさんが提示された乗算と回転をご利用しても色々出来ますし、
便利命令をまとめて下さっている方もいらっしゃるので、
是非ともチャレンジしてみて頂きたのですが、
今取り組んでいるゲームプログラムでなんとかなっている
との事なので、そのままでも良い様な気もしました。

※過去ログ NO.93927, NO.93930 に私が関数化したサンプルもあるので、
 もしご参考になればどうぞ。(掲示板どうやって検索するんだろう)

 クォータニオン自身の値に関しては人間が理解する必要はなく、
 足算や掛算をするように"どの様な操作をしたか"という事が重要かと思います。
 (4次元は私たち3次元の物からするとイメージしにくいので直感的な数字にはならないので)

以上、長々としつれいいたしました。



アキアキノヒロロ

リンク

2024/4/17(Wed) 05:08:10|NO.101543

buhioさん、usagiさん、更なるご返答ありがとうございます。

何か、お二人の間では、解決しているような......。
私は、まだ理解の入口に立ったばかりです。

>疑似相関みたいな事でしょうか。(usagiさん)

自分もそう思い、usagiさん同様に、

>角度はラジアンなので1は大体60度くらいになります。
>平面に近づくと[0.7, 0.7, 0]ですがYは無視する作りなので、0.7radは40度くらい。

このことを考えていました。

>どんな法線でも満たすのか確認してみて

ということで、今検証用のプログラムを作っているところです。
これがどうにか作れて、自分なりに、「少しはスッキリ」したら、
「解決」としたいと思いますので、もう少しお時間を。

buhioさんの「乗算」と「回転」も使わせて頂こうと思います。
ただ、[#deffunc]に慣れていないので、こちらも時間が。

>(掲示板どうやって検索するんだろう)
「usagi クォータニオン」で、過去ログ検索できました。

本当に、お二人には、頭が上がりません。



アキアキノヒロロ

リンク

2024/4/17(Wed) 05:46:21|NO.101544

言い忘れました。

buhioさんのもの、直感的に掴めて、よかったです。

「クォータニオン」毛嫌いせず、どんどん使って、使い慣れてしまえばいいのか、とも。


usagiさんの「どんな法線でも満たすのか」の一例としてご提示された「天井に忍者の様に立つ形」

揚げ足取りのようになって申し訳ないですが、これは確かに検証に必要なことと理解はしておりますが、
私の「デコボコ地面走行時の車の傾き再現」には、まずありえないことなので、
「地面走行」というのが、usagiさんのおっしゃる「特定条件下」になっているように思います。
(「地面走行」を外す実例としては、渦巻き宙返りするジェットコースターですか。)

「地面走行」という「特定条件下」での「疑似相関」......?



usagi

リンク

2024/4/17(Wed) 11:27:38|NO.101546

混乱させてしまいましたね。すみません。


>解決しているような......。
いえ、全然解決しておらずずっと考えてますよ。
どうやって実現したのか、全くもって分かってないですし、
私のテストだとご提示の方法は上手くいきませんでした。

前も書きましたが、アキアキノヒロロさんの問はいつも難易度が高く、
推理小説を解くかのように楽しんでます。(私、過去一度も正解してませんが泣)

「合っているか?」という証明はすごく難しいですよね。
範囲が広すぎますので、条件を絞る形でスッキリにもっていけたらと考えてました。

「ベクトル」「角度」の考え方としては間違っていて、(学習的な意味として)
条件を絞ったウラ技としては合っている可能性があるのでは考えてます。(私は動作未確認)


>ということで、今検証用のプログラムを作っているところです。

すごく、楽しみにしてます!


>揚げ足取りのようになって申し訳ないですが、
>私の「デコボコ地面走行時の車の傾き再現」には、まずありえないことなので

全然、揚げ足とは思ってないですよ。
地面というのは球状地球ではなくて、平面地球みたいな事ですよね?(箱庭的な)
私も傾斜がきつくなると成立しないのではと思ってたので、
少し凸凹な平面であればガタガタ動いて雰囲気は出そうなきがしました。

物理演算の時にお話ししたかもしれませんが、
私はゲームに関しては理論より結果派なので、
条件を絞って最適化をする事も多いですから、
ありえる条件で、理想の結果が満たされていればよろしいかと考えてます。

※余談※
先日OBSLiveで吉村ことりさんがゲスト参加されてましたが、
8bitパソコンで3Dに陰影付けてたんですよね。
「すごい!」と思ってたら、すかさずおにたまさんが「内積とってる」とツッコミ入れてて
ことりさんが「内積とってます。カメラが一方向なのでシフトでいける。。。」
みたいな事をお話しされていて(記憶ちがってたらすみません)
これも条件を絞った最適化だと思ってます。



アキアキノヒロロ

リンク

2024/4/17(Wed) 19:19:20|NO.101547

usagiさんのものは、「Yは無視する作り」とのこと。
buhioさんのものは、
>; 上方向ベクトルを用意 (単位ベクトル)
>fvset vec_up, 0.0, 1.0, 0.0
となっています。

このままの形では、モデルをY軸回転させている私のプログラム用の検証は、できそうにありません。
buhioさんのものの、上方向の単位ベクトルを
[←,→]等の回転操作キーで回転させたモデルのベクトルに変えるには
どうしたらいいのか、やり方が分かりません。



アキアキノヒロロ

リンク

2024/4/17(Wed) 19:38:11|NO.101548

[chdir dir_exe+"\\sample\\hgimg4"]でスクリプトが組めればいいのですが、難しいので、
ちょっと長くなってしまいますが。とりあえず、
#include "hgimg4.as"
gpreset setcls CLSMODE_SOLID, $404040 test=0 //0//1 ; 軸 (右手座標 Y UP) gpbox id_axis_x, 0.5, $FF0000 : setpos id_axis_x, 25 : setscale id_axis_x, 100,1,1 gpbox id_axis_y, 0.5, $00FF00 : setpos id_axis_y, ,25 : setscale id_axis_y, 1,100,1 gpbox id_axis_z, 0.5, $0000FF : setpos id_axis_z, ,,25 : setscale id_axis_z, 1,1,100 ;------------------------------------------------------------------------------ gpbox id_floor, 25, $ffaaff setscale id_floor, 1.0, 0.01, 1.0 ; 床(箱)ノードを追加 gppbind id_floor, 0, ; 床コリジョンとして gpload id_ball,"res/ball" ; 山(球体)ノード読み込み setscale id_ball, 0.8,0.8,0.8 if test=0 : setpos id_ball, 0.0, -5.0, 0.0 if test=1 : setpos id_ball, 0.0, 0.0, 0.0 gppbind id_ball, 0, , GPPBIND_MESH ; 物理設定 (コリジョンとしてノードのモデルを反映) ;------------------------------------------------------------------------------ gpload id_chara,"res/jeep0" ; 車モデル読み込み setscale id_chara, 0.01,0.01,0.01//,0.015,0.015,0.015 setpos id_chara, -10.0, 0.0, 0.0 setalpha id_chara, 192 ; ------------------------------------------------------------------------------ gpbox id_model_board, 1, 0x00ff00 ; 緑色板モデル読み込み setscale id_model_board, 1.0, 8.0, 0.25 setpos id_model_board, -10.0, 0.0, 0.0 setalpha id_model_board, 192 ; ------------------------------------------------------------------------------ gpbox id_null, 0.5, 0xffff00 ; 高度取得用=黄色 setpos id_null, 0, 5.0, 0 ; [5.0]上に setang id_null, -M_PI/2.0, 0, 0 ; M_PI 円周率 ; ------------------------------------------------------------------------------ gpbox id_null_0, 0.3, 0xff0000 ; 衝突地点用=赤色 gpbox id_null_1, 0.3, 0x00ffff ; 法線終点用=水色 ; ------------------------------------------------------------------------------ ; カメラ位置を設定 if test=0 : setpos GPOBJ_CAMERA, 0.0,5.0,30.0 if test=1 : setpos GPOBJ_CAMERA, 0.0,10.0,30.0 ; ------------------------------------------------------------------------------ speed = 0.05 ;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ *main_loop stick key,15 if key&128 : end ;〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓 ;カメラ位置を動かす//96〜105 : [0]〜[9](テンキー) getkey k, 100 : if k : addpos GPOBJ_CAMERA, -0.2, 0, 0 ; ■■ [4]キー getkey k, 102 : if k : addpos GPOBJ_CAMERA, 0.2, 0, 0 ; ■■ [6]キー getkey k, 104 : if k : addpos GPOBJ_CAMERA, 0, 0,-0.2 ; ■■ [8]キー getkey k, 98 : if k : addpos GPOBJ_CAMERA, 0, 0, 0.2 ; ■■ [2]キー getkey k, 101 : if k : addpos GPOBJ_CAMERA, 0, 0.2, 0 ; ■■ [5]キー getkey k, 96 : if k : addpos GPOBJ_CAMERA, 0,-0.2, 0 ; ■■ [0]キー gplookat GPOBJ_CAMERA, 0,5,0 ; カメラから指定した座標を見る ;〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓 ; カーソルキーでキャラクターを動かす fvset fv_vel, 0, 0, 0 ; 進行方向ベクトル if key&1 { ; ■■ [←]キー ←左回転 addang_cnt+ addang id_chara, 0, 0.01, 0 ; 珠音モデル addang id_model_board, 0, 0.01, 0 ; 緑色板モデル if (0.01*addang_cnt > M_PI*2) : addang_cnt=0 } if key&4 { ; ■■ [→]キー →右回転 addang_cnt- addang id_chara, 0, -0.01, 0 ; 珠音モデル addang id_model_board, 0, -0.01, 0 ; 緑色板モデル if (-0.01*addang_cnt > M_PI*2) : addang_cnt=0 } if key&2 { ; ■■ [↑]キー fvset fv_vel, 0, 0, speed } gosub *move_model ;〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓 redraw 0 ; 描画開始 gpdraw ; シーンの描画 color 0,0,0 : boxf 0,0, ginfo(10),80 getpos id_null, nx, ny, nz getpos id_null_0, n0x, n0y, n0z getpos id_null_1, n1x, n1y, n1z ;------------------------------------------------------------------------------ gpcnvaxis var_x,var_y,var_z, nx,ny,nz, 0 ; 3D座標を 2D座標へ変換 // pos var_x,var_y //高度取得用=黄色 ;------------------------------------------------------------------------------ gpcnvaxis var0_x,var0_y,var0_z, n0x,n0y,n0z, 0 ; 3D座標を 2D座標へ変換 // pos var0_x,var0_y //衝突地点用=赤色 ;------------------------------------------------------------------------------ gpcnvaxis var1_x,var1_y,var1_z, n1x,n1y,n1z, 0 ; 3D座標を 2D座標へ変換 // pos var1_x,var1_y //法線終点用=青色 ;------------------------------------------------------------------------------ color 255,255,0 line var0_x,var0_y, var_x,var_y //高度取得用ベクトル線分 color 0,255,255 line var0_x,var0_y, var1_x,var1_y //法線ベクトル線分 ;------------------------------------------------------------------------------ pos 100,5 color 255,255, 0 : mes "高度取得用 = "+nx+" / "+ny+" / "+nz+" ◆ 高度取得用ベクトル線分" color 255, 0, 0 : mes "衝突地点用 = "+n0x+" / "+n0y+" / "+n0z color 0,255,255 : mes "法線終点用 = "+n1x+" / "+n1y+" / "+n1z+" ◆ 法線ベクトル線分" color 0,255, 0 : mes "代用ラジアン = "+vector_x+" / "+vector_y+" / "+vector_z+" ◆ モデル設定角度用" redraw 1 ; 描画終了 await 1000/60 ; 待ち時間 goto *main_loop ;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ *move_model ;[id_chara] キー入力による移動(fv_vel)とジャンプ(fv_jump) ; [id_chara](ノード)の向きを 初期値状態に比べてどのくらいの角度を向いているかで取得 getang id_chara, xr, yr, zr fvset fvr, xr, yr, zr ; 進行方向ベクトルを現在の[id_chara](ノード)の向きに回転 ;■ ベクトル乗算 fvmul fvr, -1,-1,-1 ;◆◆◆◆◆ fvdir のバグ対策 ◆◆◆◆◆ ;■ ベクトル回転 ;■ [if key&2] キー操作による回転 fvdir fvr, fv_vel(0), fv_vel(1), fv_vel(2) ; 現在の向きに合わせた進行方向ベクトルを現在値に加算 addpos id_chara, fvr(0), fvr(1), fvr(2) ; 珠音モデル addpos id_model_board, fvr(0), fvr(1), fvr(2) ; 緑色板モデル ; [id_chara]の位置をヌルノードにセット getpos id_chara, px, py, pz setpos id_null_0, px, py, pz setpos id_null, px, py+5.0, pz ; 地面との接触がある場合は、珠音の高さを地面に合わせる。 gppraytest objid, id_null, 10.0 if (objid > 0) { getwork id_null, wx, height, wz gosub *work2 } ; ジャンプ if flgJump = 1 { ; ジャンプ中(空中) ; 重力加速度の分だけジャンプ速度を減速 addpos id_chara, fv_jump(0), fv_jump(1), fv_jump(2) fvsub fv_jump, 0, 9.8/60, 0 ; ジャンプ終了条件 getpos id_chara, px, py, pz if py < height { setpos id_chara, px, height, pz fvset fv_jump, 0,0,0 flgJump = 0 } } else { ; [id_chara]の位置を地面高さに移動する。 getpos id_chara, px, py, pz setpos id_chara, px, height, pz ; 珠音モデル setpos id_model_board, px, height, pz ; 緑色板モデル } return ;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ *work2 ; Y軸回転を最初に設定の [setangy](Y->X->Zの順番) でならば、 ; その向きでのX,Z軸回転の設定になるだろうから、 ; 一旦、[getwork2] で得た値を、[setangy] で、その順番で設定し、 ; [addang] で、Y軸だけその分 [ー] して元に戻してやる。 ; その上で、キー操作による回転方向角度をY軸に [+] してやる。 getwork2 id_null,vector_x,vector_y,vector_z ; 珠音モデル setangy id_chara, vector_x,vector_y,vector_z addang id_chara, 0.0, -vector_y, 0.0 addang id_chara, 0.0, (0.01*addang_cnt), 0.0 ; 緑色板モデル setangy id_model_board, vector_x,vector_y,vector_z addang id_model_board, 0.0, -vector_y, 0.0 addang id_model_board, 0.0, (0.01*addang_cnt), 0.0 getpos id_chara, px, py, pz getwork2 id_null,vector_x,vector_y,vector_z setpos id_null_1,px+vector_x*4.5, py+vector_y*4.5, pz+vector_z*4.5 return
分かりづらいと思うので、恐縮ですが、私の『X』を見ていただけるとありがたいです。
取りあえず、画像です。(のちに動画も)
また、宣伝か、と言われそうですが。

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



アキアキノヒロロ

リンク

2024/4/17(Wed) 21:11:47|NO.101550

今作っている『デコボコレース』というゲーム、
https://twitter.com/akiakinohiroro/status/1758662501242429737
https://twitter.com/akiakinohiroro/status/1764151399456338311

地面のデコボコ度を極端にもっと上げて、切り立った崖のような地形にしても、
ゲームとしては、現状、それなりに見られる(ゴマカシが効く)程度に収まっています。
もちろん、反転しているような崖は、標高を求める「ヌル」の設定が不都合になるので、
そこまでのデコボコ度ではありませんが。

またまた、『X』を持ち出してすいません。
3Dは、どうしてもこうなりがちなのをご理解下さい。
検証の動画、お待ちください。(待ってないか)

なお、検証スクリプトの、[id_chara](珠音でなく車)は向きがわかるようにした[box]に、
そして、山代用の[id_ball]も適当なものに置き換えて、実行してみて頂けると、ありがたいです。



usagi

リンク

2024/4/17(Wed) 21:51:49|NO.101551

わぉ、面白そうですね。

>usagiさんのものは、「Yは無視する作り」とのこと。

また説明が足りませんでした、ご提示された方法が
法線に対してY軸を+-打ち消す作りの様に見えたので、
0〜60度くらいで、試行錯誤とあいまっていい感じにガタガタ動いているのでは?
というアキアキノヒロロさんのお持ちのスクリプトに対する想像でした。
(法線ベクトルを角度値にはそのまま利用できないですよという意味合い)

私のサンプルに関しては法線に立つだけでY軸回転はしてなかったので、
説明とサンプルが同じ事と混同させてしまいました。
申し訳ございません。

法線方向に立っていれば後はそれを軸にして回すだけなので、
簡単に対応できますから少々お待ちくださいませ。

ゲーム動画も拝見しました。雰囲気イイ感じではないでしょうか。
ゲーム性も面白いですね。

逆にしっかり法線に立つと車のサスを再現や補間しないと上手く
振動感が出ないとも思いますので、(未来の車的な)
可愛らしい雰囲気ともあいまって、面白い動きになってます。

考えが合ってるかどうかのご質問で言うと間違っていると思うのですが、
(Xのスクショの法線ともズレているので)
十分雰囲気が出ていて、私はよろしいのではと思いました。



usagi

リンク

2024/4/17(Wed) 22:23:24|NO.101552

どうぞ! (ラジオコン移動には対応してません)

#include "hspmath.as" #include "hgimg4.as" ; ★掲示板NO.93927からのコピペ(中身は理解する必要は無い) #module #deffunc qtset array a_qt, double a_x, double a_y, double a_z, double a_w _r = a_w / 2 : _sin = sin(_r) a_qt.0 = a_x * _sin : a_qt.1 = a_y * _sin : a_qt.2 = a_z * _sin a_qt.3 = cos(_r) return #deffunc qtmul array a_qt, array a_q1, array a_q2 a_qt.0 = a_q1.3*a_q2.0 + a_q2.3*a_q1.0 + a_q1.1*a_q2.2 - a_q1.2*a_q2.1 a_qt.1 = a_q1.3*a_q2.1 + a_q2.3*a_q1.1 - a_q1.0*a_q2.2 + a_q1.2*a_q2.0 a_qt.2 = a_q1.3*a_q2.2 + a_q2.3*a_q1.2 + a_q1.0*a_q2.1 - a_q1.1*a_q2.0 a_qt.3 = a_q1.3*a_q2.3 - a_q1.0*a_q2.0 - a_q1.1*a_q2.1 - a_q1.2*a_q2.2 return #global screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 ; カメラ setpos GPOBJ_CAMERA, 0,10,10 : gplookat GPOBJ_CAMERA, 0,0,0 ; 軸 (右手座標 Y UP) gpbox id_axis_x, 0.1, $FF0000 : setpos id_axis_x, 5 : setscale id_axis_x, 100,1,1 gpbox id_axis_y, 0.1, $00FF00 : setpos id_axis_y, ,5 : setscale id_axis_y, 1,100,1 gpbox id_axis_z, 0.1, $0000FF : setpos id_axis_z, ,,5 : setscale id_axis_z, 1,1,100 ; 床 gpbox id_floor, 1, $00FFFF : setpos id_floor, 0,0 : setscale id_floor, 10, 0.1, 10 gppbind id_floor, 1 gppset id_floor,GPPSET_KINEMATIC,1 ; モデル gpload id_model,"res/tamane2" setscale id_model, 0.01,0.01,0.01 r=0.0f : i=1.0f *main if r>1.4{i=-1}:if r<=-1.4{i=1}:r+=(0.01f*i):setang id_floor,0,0,r gppraytest id, GPOBJ_CAMERA, 100 getwork GPOBJ_CAMERA, loc.0, loc.1, loc.2 getwork2 GPOBJ_CAMERA, norm.0, norm.1, norm.2 ; 法線方向に立つ(前回のサンプル) fvset vec_up, 0.0, 1.0, 0.0 fvset vec_axis, vec_up.0, vec_up.1, vec_up.2 fvouter vec_axis, norm.0, norm.1, norm.2 : fvunit vec_axis fvset dot, vec_up.0, vec_up.1, vec_up.2 fvinner dot, norm.0, norm.1, norm.2 ang_rad = acos(dot.0) qtset qua, vec_axis.0, vec_axis.1, vec_axis.2, ang_rad ; ★★ここから追加★★ ; キー入力 getkey ←, 37 : getkey →, 39 if ← : ang_model = 0.1 + ang_model if → : ang_model = -0.1 + ang_model ; 1)法線の軸に対して回転させたクォータニオンを作成 qtset qua2, norm.0, norm.1, norm.2, ang_model ; 2)軸に立ったクォータニオンと軸に回転させたクォータニオンを合成 qtmul qua3, qua2, qua ; 3)モデルにセット setquat id_model, qua3.0, qua3.1, qua3.2, qua3.3 ; ★★ここまで★★ redraw 0 gpdraw color 255,255,255 : pos 0,0 mes strf("法線:%3.2f, %3.2f, %3.2f", norm.0, norm.1, norm.2) mes strf("←→キーで向き:%3.2f", rad2deg(ang_model)) redraw 1 await 1000/60 goto *main



buhio

リンク

2024/4/18(Thu) 01:19:35|NO.101553

必死でついていきます!!(ラジコン操作対応)

>>アキアキノヒロロさん
ゲーム画面を拝見しました。
アナログなタコメーター表示や、アニマルをガンガン轢きまくるのが良いです。
スカイボックスがすごいきれい。どうやってるんでしょうか。。あんなにきれいな雲にできないんですよね。
・・・おやすみなさい


#include "hspmath.as" #include "hgimg4.as" ; ★掲示板NO.93927からのコピペ(中身は理解する必要は無い) #module #deffunc qtset array a_qt, double a_x, double a_y, double a_z, double a_w _r = a_w / 2 : _sin = sin(_r) a_qt.0 = a_x * _sin : a_qt.1 = a_y * _sin : a_qt.2 = a_z * _sin a_qt.3 = cos(_r) return #deffunc qtmul array a_qt, array a_q1, array a_q2 a_qt.0 = a_q1.3*a_q2.0 + a_q2.3*a_q1.0 + a_q1.1*a_q2.2 - a_q1.2*a_q2.1 a_qt.1 = a_q1.3*a_q2.1 + a_q2.3*a_q1.1 - a_q1.0*a_q2.2 + a_q1.2*a_q2.0 a_qt.2 = a_q1.3*a_q2.2 + a_q2.3*a_q1.2 + a_q1.0*a_q2.1 - a_q1.1*a_q2.0 a_qt.3 = a_q1.3*a_q2.3 - a_q1.0*a_q2.0 - a_q1.1*a_q2.1 - a_q1.2*a_q2.2 return #global screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 ; カメラ setpos GPOBJ_CAMERA, 0,10,10 : gplookat GPOBJ_CAMERA, 0,0,0 ; 軸 (右手座標 Y UP) gpbox id_axis_x, 0.1, $FF0000 : setpos id_axis_x, 5 : setscale id_axis_x, 100,1,1 gpbox id_axis_y, 0.1, $00FF00 : setpos id_axis_y, ,5 : setscale id_axis_y, 1,100,1 gpbox id_axis_z, 0.1, $0000FF : setpos id_axis_z, ,,5 : setscale id_axis_z, 1,1,100 ; 床 gpbox id_floor, 1, $00FFFF : setpos id_floor, 0,0 : setscale id_floor, 10, 0.1, 10 gppbind id_floor, 1 gppset id_floor,GPPSET_KINEMATIC,1 ; モデル gpload id_model,"res/tamane2" setscale id_model, 0.01,0.01,0.01 r=0.0f : i=1.0f ;●レイテスト用ボックス gpbox id_box,0.5 *main if r>1.4{i=-1}:if r<=-1.4{i=1}:r+=(0.01f*i):setang id_floor,0,0,r gppraytest id, GPOBJ_CAMERA, 100 getwork GPOBJ_CAMERA, loc.0, loc.1, loc.2 getwork2 GPOBJ_CAMERA, norm.0, norm.1, norm.2 ; 法線方向に立つ(前回のサンプル) fvset vec_up, 0.0, 1.0, 0.0 fvset vec_axis, vec_up.0, vec_up.1, vec_up.2 fvouter vec_axis, norm.0, norm.1, norm.2 : fvunit vec_axis fvset dot, vec_up.0, vec_up.1, vec_up.2 fvinner dot, norm.0, norm.1, norm.2 ang_rad = acos(dot.0) qtset qua, vec_axis.0, vec_axis.1, vec_axis.2, ang_rad ; ★★ここから追加★★ ; キー入力 getkey ←, 37 : getkey →, 39 getkey ↑, 38 : getkey ↓, 40 if ← : ang_model = 0.1 + ang_model if → : ang_model = -0.1 + ang_model ; 1)法線の軸に対して回転させたクォータニオンを作成 qtset qua2, norm.0, norm.1, norm.2, ang_model ; 2)軸に立ったクォータニオンと軸に回転させたクォータニオンを合成 qtmul qua3, qua2, qua ; 3)モデルにセット setquat id_model, qua3.0, qua3.1, qua3.2, qua3.3 ; ★★ここまで★★ ;=====●追加 if ↑ : addfwd id_model, 0.1,0,0,1 if ↓ : addfwd id_model,-0.1,0,0,1 getpos id_model,x,y,z:getquat id_model ,qx,qy,qz,qw setpos id_box ,x,y,z:setquat id_box ,qx,qy,qz,qw addfwd id_box ,5,0,1,0 gplookat id_box,x,y,z gppraytest var,id_box,100 if var>0{ getwork id_box ,wx,wy,wz setpos id_model,wx,wy,wz } ;=====●ここまで redraw 0 gpdraw color 255,255,255 : pos 0,0 mes strf("法線:%3.2f, %3.2f, %3.2f", norm.0, norm.1, norm.2) mes strf("←→キーで向き:%3.2f", rad2deg(ang_model)) mes "↑↓キーで前進後退" redraw 1 await 1000/60 goto *main ;============================================================================= ;XYZ軸への前進(forword)を行うクオータニオンを生成する;ローカル座標の計算のショートカット命令 ;_speed変数が速度、_sx,_sy,_szをそれぞれ1にするとその方向へ進む #deffunc addfwd int _id_model,double _speed,double _sx,double _sy,double _sz sx=_sx*_speed;←1にするとx軸への前進 sy=_sy*_speed;←1にするとy軸への前進 sz=_sz*_speed;←1にするとz軸への前進 sw=0f getquat _id_model,qx,qy,qz,qw vec4_a=qx,qy,qz,qw ;現在クオータニオン vec4_b=sx,sy,sz,sw ;ローカル位置 vec4_c=-qx,-qy,-qz,qw;共役クオータニオン qtmul vec4_d,vec4_a,vec4_b qtmul vec4_e,vec4_d,vec4_c getpos _id_model,px,py,pz setpos _id_model,vec4_e(0)+px,vec4_e(1)+py,vec4_e(2)+pz;新位置=結果+旧位置 return



usagi

リンク

2024/4/18(Thu) 05:01:18|NO.101554

>buhioさん
すごっ!なんか共同でプログラム組んでる見たいで面白いですね。
新たな発見があって勉強になりまする。"addfwd"超便利な命令追加してる!保存しました(笑)
寝ようと思ったのですが、思わずコメントしちゃいまいした。


>アキアキノヒロロさん
検証スクリプトありがとうございます。
私はモデルを持ってないのでid_ballをduckの頭,id_charaをtamane2に置き換えて確認しました。

色々試しましたが、法線にそってはおらず、
傾向として法線がX軸方向の時は角度がずれていきZ軸方向は逆方向を向いているようでした。
※ただ、そのガタガタ感がゲームの味になっているのかも
※あと、傾斜がキツイ所はかえって法線に添わない事により平地から入った時に滑らかに見える(傾きすぎないので)

というわけで、ご提示いただい検証に似たようなアプローチで法線にモデルを添わせてみました。
色々な角度で検証しましたが、法線にそった形になっていると思います。
※buhioさんのサンプルの方がもっと高度な事ができると思います。

やはり、"教えて"スレの回答としては、前後左右の傾きを取得再現利用は出来ていないと思いますし、
考え方としても合っていないと思います。スッキリしますかねぇ。。。

※もしかして私、質問の意図を勘違いしているのかなぁ。いつにもまして難しいですね。
※作られた物を否定する意味ではないですので悪しからず。素晴らしいゲームだと思います。


#include "hspmath.as" #include "hgimg4.as" #module #deffunc qtset array a_qt, double a_x, double a_y, double a_z, double a_w _r = a_w / 2 : _sin = sin(_r) a_qt.0 = a_x * _sin : a_qt.1 = a_y * _sin : a_qt.2 = a_z * _sin a_qt.3 = cos(_r) return #deffunc qtmul array a_qt, array a_q1, array a_q2 a_qt.0 = a_q1.3*a_q2.0 + a_q2.3*a_q1.0 + a_q1.1*a_q2.2 - a_q1.2*a_q2.1 a_qt.1 = a_q1.3*a_q2.1 + a_q2.3*a_q1.1 - a_q1.0*a_q2.2 + a_q1.2*a_q2.0 a_qt.2 = a_q1.3*a_q2.2 + a_q2.3*a_q1.2 + a_q1.0*a_q2.1 - a_q1.1*a_q2.0 a_qt.3 = a_q1.3*a_q2.3 - a_q1.0*a_q2.0 - a_q1.1*a_q2.1 - a_q1.2*a_q2.2 return #global screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 ; 設定(余り重要でないので掲示板用に短縮) setpos GPOBJ_CAMERA, 0,15,15 : gplookat GPOBJ_CAMERA, 0,0,0 gpbox id_floor, 1, $00FFFF : setscale id_floor, 50, 0.1, 50 : gppbind id_floor, 0 gpload id_duck,"res/duck" : setpos id_duck,-3,-8 : setscale id_duck, 10,10,10 gppbind id_duck, 0 ,, GPPBIND_MESH gpload id_model,"res/tamane2" : setscale id_model, 0.01,0.01,0.01 gpbox id_box,0.5,0xff00ff : setpos id_box, 0,5,0 : setang id_box,-M_PI/2 speed = 0.05 ; メインループ *main ; 2D的なラジコン回転移動 getkey ←, 37 : getkey →, 39 : getkey ↑, 38 : getkey ↓, 40 if ← : ang_model = 0.1 + ang_model if → : ang_model = -0.1 + ang_model if ↑ : addpos id_box, sin(ang_model)*speed,, cos(ang_model)*speed if ↓ : addpos id_box,-sin(ang_model)*speed,,-cos(ang_model)*speed ; アキアキノヒロロさんの様な2D移動に高さを+した様なアプローチ ; 高度用のボックスから下にレイキャスト(なので反り返る崖は対応出来ない) gppraytest var,id_box,100 getwork id_box, wx,wy,wz getwork2 id_box, norm.0, norm.1, norm.2 setpos id_model,wx,wy,wz setpos id_box,wx,wy+5,wz gpcnvaxis s.0, s.1, s.2, wx,wy,wz gpcnvaxis e.0, e.1, e.2, wx+norm.0, wy+norm.1, wz+norm.2 ; 法線方向に立って回転(前回から変更なし) fvset vec_up, 0.0, 1.0, 0.0 fvset vec_axis, vec_up.0, vec_up.1, vec_up.2 fvouter vec_axis, norm.0, norm.1, norm.2 : fvunit vec_axis fvset dot, vec_up.0, vec_up.1, vec_up.2 fvinner dot, norm.0, norm.1, norm.2 ang_rad = acos(dot.0) qtset qua, vec_axis.0, vec_axis.1, vec_axis.2, ang_rad qtset qua2, norm.0, norm.1, norm.2, ang_model qtmul qua3, qua2, qua setquat id_model, qua3.0, qua3.1, qua3.2, qua3.3 ; --------------------- redraw 0 : gpdraw color 255,0,255 : line s.0, s.1, e.0, e.1 mes strf("法線:%+1.2f, %+1.2f, %+1.2f", norm.0, norm.1, norm.2),4 redraw 1 : await 1000/60 goto *main


※余談※
>ただ、[#deffunc]に慣れていないので、こちらも時間が。
ご存じでしたら申し訳ないですが、マニュアルはこちらです。
https://www.onionsoft.net/hsp/v33/doclib/module.htm

新規命令を追加するものなので、基本コピペで良いとは私は思ってます。
※私は教えてスレに書き込んだスクリプトに権利主張するのはナンセンス派なので。。。
 (そういうのはオープンにするべきでないし、プロプライエタリでやってねと)

中身に興味が出たら、質問や解析するとかがよろしいかと存じますので、
気楽に使い始めてみるとアキアキノヒロロさん作品規模だと、
記載量が大幅に減るので、結果としてかなり時短になりそうと思いました。

たとえば line と言う命令を普段使うと思いますが、その中身はものすごく複雑なんですよね。
それを誰でも簡単に使えるように命令の形で提供しているわけです。
circle と言う命令もありますが、私は以前、円を描くことも出来ず挫折した事があり
最近は自前で円を描くのではなくこの命令にたよりきってます。



アキアキノヒロロ

リンク

2024/4/18(Thu) 07:22:18|NO.101555

私の[getwork2]の検証で、やはり、モデルの傾きが法線とズレていること、
視覚的にはっきりしました。

スレッド冒頭に書きましたように、

>この[getwork2]の取得値を角度のように勘違いしていました。

全ては、この『勘違い』から始まりました。

その地点における、法線ベクトルの各成分の正規化数値であるものを、
まるで、法線ベクトルの角度を[X,Y,Z]の形で表わしたもの、
[setang]等に使える「ラジアン」であるかのごとく、『勘違い』思い違いをしたのでした。
そこから、悪戦苦闘、試行錯誤、トライ&エラー、で行き着いたのが、私の[getwork2]方式でした。
ですから、『勘違い』に気づいてからは、この方式が考え方として間違っているだろうことは、
うすうす分かっていました。それにも関わらず、

>偶然だとしても、偶然に思えない何かがある

実際上、そう感じてしまうほどに、プログラム実行結果が上手く都合よく動いてくれたのです。

usagiさんのおっしゃるように
>傾向として法線がX軸方向の時は角度がずれていきZ軸方向は逆方向を向いているようでした。
>傾斜がキツイ所はかえって法線に添わない事により平地から入った時に滑らかに見える
(Z軸方向は逆方向.....これが分からないのですが)

『X』の動画は、モデル後方すぐの地点からのカメラ視点、
および車載カメラ視点(動きが車に同期)なので、ゴマカシが出来ているようにも思います。
しかし、ある程度の距離からの別カメラ視点の動画(またで、すいません)を目を凝らしてみても、
上手く行き過ぎていると、自分ながら思ってしまったのです。
(全画面拡大表示で確認 / もちろん、プログラム実行でも確認)
https://twitter.com/akiakinohiroro/status/1726143022717673911
https://twitter.com/akiakinohiroro/status/1732535218354241657

で、何故、そうなってくれたのか、不思議に思い、考えてみたくなったのでした。

>buhioさん、usagiさん
こんな『勘違い』に、長くお付き合いいただき、本当にありがとうございました。

特定の命令を毛嫌いせず、拒絶反応を克服して、頑張っていきたいと思います。
以上、一応の解決と致します。

それで、次なる目標は、
『渦巻き宙返りするジェットコースター』



アキアキノヒロロ

リンク

2024/4/19(Fri) 05:25:31|NO.101559

解決としましたが、usagiさんご指摘の
>Z軸方向は逆方向を向いている
が、どうしても気になって、色々やってみました。

[←,→]キーによる[addang]で増減させる値を変えてみた場合のことですが、
[if]の中の[〇〇*addang_cnt]の箇所もその値に直すとともに、
[*work2]内の[〇〇*addang_cnt]も変更しないと、回転がおかしくなります。
例えば、値を[1][-1]から、[2][-2]に変えた場合、[*work2]内を変更し忘れると、
モデルを半回転させた時点で、向きが反転してしまいます。
usagiさんの「逆方向」はこの状態かと思います。
違っていたら、すいません。

動画、載せました。



usagi

リンク

2024/4/19(Fri) 17:52:19|NO.101560

解決。。。してなかったですねぇ。。。ザンネン。
すみません。私はソーシャルサービスを利用していないので、動画が見れていないのですが。

>usagiさんの「逆方向」はこの状態かと思います。
いいえ、モデルを標準のサンプルに変更した以外、スクリプトの改変は行っておりません。
XY平面の第1,2象限で(デフォのカメラ+z側から原点を見た時)の法線に対する角度で

>X軸方向の時は角度が
左から右へ-xから+xへ車を移動した時は角度がズレる。
(法線に対しY軸に対しての角度が浅くなる)
※法線が[-1,0,0]->[0,1,0]->[1,0,0] の範囲という意味

>Z軸方向は逆方向
後から前へ、-zから+zへ車を移動した時はXY平面で法線の方向と線対称の方向になる。
(これを逆に傾いてると表現しました)
※法線が[0,0,-1]->[0,1,0]->[0,0,-1] の範囲という意味

オイラー角の回転順番の問題と、法線0〜1を角度radにそのままツッコむという
使用方法によりその様になると思われますし、実際にその様になっておりました。

車をtamaneの様な伸長が高いモデルに変更してみると法線と合っていない事がハッキリと分かるかと思います。

ご回答になっておりますでしょうか。



アキアキノヒロロ

リンク

2024/4/20(Sat) 00:23:47|NO.101571

3Dの傾きを言葉で正確に表現するのは難しい。

「モデルを標準のサンプルに変更」しただけなんですね。
(車をtamaneに、球体をアヒルの頭に)

私の「車と球体のスクリプト」でも、法線と合っていない事はハッキリと確認できております。
緑色の板(tamaneの代りになってます)と法線(水色の線分)は、
球体の頂点にきた時以外、重なることがないですから。
ただ、その、法線とのズレの法則性、のようなものが掴めなかったのです。

>傾向として法線がX軸方向の時は角度がずれていきZ軸方向は逆方向を向いているようでした。
これをより砕いてご説明いただいたのが、
>X軸方向の時は角度が
>Z軸方向は逆方向
の2項ですね。
ただ、このご説明の言葉だと、X軸方向とZ軸方向では、別の法則が働いていて、
共通するようなものがない、通底するものがないかのように読めてしまいます。
最後までよく読めば、
>オイラー角の回転順番の問題と、法線0〜1を角度radにそのままツッコむという
>使用方法によりその様になると思われますし、実際にその様になっておりました。
ですから、これが「法線とのズレの法則性」なんだと分かります。

しつこいようですが、usagiさんの2項を私なりの言葉で、
X軸方向条件下と、Z軸方向条件下での共通するものに留意しながら、説明したいと思います。

>X軸方向条件下(XY平面=[Z=0])
左から右へ-xから+xへ車を移動した時は、-Z方向に大きく傾いて(ズレて)始まり、
そのズレが小さくなっていき、球体の頂点にきて、傾きのズレはなくなり、完全に重なり、
頂点を過ぎて+xへ進んでいくと、+Z方向に徐々に傾いて、そのズレが大きくなっていく。

>Z軸方向条件下(ZY平面=[X=0])
後から前へ-zから+zへ車を移動した時は、+X方向に大きく傾いて(ズレて)始まり、
そのズレが小さくなっていき、球体の頂点にきて、傾きのズレはなくなり、完全に重なり、
頂点を過ぎて+zへ進んでいくと、-x方向に徐々に傾いて、そのズレが大きくなっていく。

これを組み合わせて

>[-X,-Z][0,0][+X,+Z]の方向
この方向で、左後から右前へ車を移動した時は、-Z+X方向に大きく傾いて(ズレて)始まり、
そのズレが小さくなっていき、球体の頂点にきて、傾きのズレはなくなり、完全に重なり、
頂点を過ぎて+x+zへ進んでいくと、+Z-x方向に徐々に傾いて、そのズレが大きくなっていく。

>[+X,-Z][0,0][-X,+Z]の方向
この方向で、右後から左前へ車を移動した時は、+Z+X方向に大きく傾いて(ズレて)始まり、
そのズレが小さくなっていき、球体の頂点にきて、傾きのズレはなくなり、完全に重なり、
頂点を過ぎて-x+zへ進んでいくと、-Z-x方向に徐々に傾いて、そのズレが大きくなっていく。

これらを総合するに、
球体の頂点から離れていくに従って、右巻き渦のように傾きがズレていきます。

相変わらず、舌っ足らずの、こねくり回したようなしつこい説明になってしまいましたが、
最後の「右巻き渦のようなズレ」で納得。
これで、本当に解決といたします。

長々と、ありがとうございました。



usagi

リンク

2024/4/20(Sat) 11:15:41|NO.101572

納得されたようで良かったです。
「右巻き渦のようなズレ」とお伝えするのが正解だったんですね。なるほど。

私の方が共通するものが無いと言う理解にたどり着く想像が出来ておらず「これを組み合わせて」
という一文を書いておけば伝わりやすかったのかもしれないと反省しております。
X方向の挙動とZ方向の挙動を分けてお伝えした方がシンプルに法則性が分かりやすいと思っていました。
(XZ平面で見たらただの合成なので想像して頂きやすいかと考えてました)

結局の所、仰られる通り法線を角度に変換すれば、この条件下ではなんら問題ないので、
説明用にクォータニオンを使わない方法を用意していたので折角ですから投稿しておきますね。(未最適化)
名付けて「右巻き渦のようなズレ回避の為、法線を角度に変換する術」です。
それでは、さようなら。


; ★新規命令追加なのでココから下の中身は気にしない。 ------- #module #define EPS 0.00000000001 #define ctype acos(%1) atan(sqrt(1f-double(%1)*(%1)),(%1)) ; 公開命令 ; --------------------------- #deffunc fvnorm2ang array o v = 0f, 1f, 0f fvlookat o, v, o : return ; 非公開命令 ; --------------------------- ; 内積 #defcfunc local dot array a, array b return a.0*b.0 + a.1*b.1 + a.2*b.2 ; 外積 #deffunc local cross array o, array a, array b o = a.1*b.2 - a.2*b.1, a.2*b.0 - a.0*b.2, a.0*b.1 - a.1*b.0 : return ; 正規化 #deffunc local normalize array o d = sqrt(o.0*o.0 + o.1*o.1 + o.2*o.2)+EPS : o = o.0/d, o.1/d, o.2/d : return ; 任意軸周りの回転 (ロドリゲスの回転公式) ※単位ベクトルを入力 #deffunc local rotvec2mtx array m, double r, array a x = a.0 : y = 0f+a.1 : z = 0f+a.2 : s = sin(r) : c = cos(r) m.0 = x*x*(1f-c) + c, x*y*(1f-c) - z*s, z*x*(1f-c) + y*s m.3 = x*y*(1f-c) + z*s, y*y*(1f-c) + c, y*z*(1f-c) - x*s m.6 = z*x*(1f-c) - y*s, y*z*(1f-c) + x*s, z*z*(1f-c) + c return ; 角度を返す XYZ #deffunc local fvlookat array o, array a, array b angle = acos(dot(a, b)) : cross axis, a, b : normalize axis : rotvec2mtx mtx, angle, axis t = -atan(mtx.5, mtx.8) : o = t, atan(mtx.2*cos(t), mtx.8), -atan(mtx.1, mtx.0) : return #global ; ★ココまでは気にしない ---------------------------------- #include "hgimg4.as" screen 0, 512, 512 : chdir dir_exe+"\\sample\\hgimg4" : gpreset : setcls CLSMODE_SOLID, 0 setpos GPOBJ_CAMERA, 0,15,15 : gplookat GPOBJ_CAMERA, 0,0,0 gpbox id_floor, 1, $00FFFF : setscale id_floor, 50, 0.1, 50 : gppbind id_floor, 0 gpload id_duck,"res/duck" : setpos id_duck,-3,-8 : setscale id_duck, 10,10,10 gppbind id_duck, 0 ,, GPPBIND_MESH gpload id_model,"res/tamane2" : setscale id_model, 0.01,0.01,0.01 gpbox id_box,0.5,0xff00ff : setpos id_box, 0,5,0 : setang id_box,-M_PI/2 speed = 0.05 *main getkey ←, 37 : if ← : ang_model = 0.1 + ang_model getkey →, 39 : if → : ang_model = -0.1 + ang_model getkey ↑, 38 : if ↑ : addpos id_box, sin(ang_model)*speed,, cos(ang_model)*speed getkey ↓, 40 : if ↓ : addpos id_box,-sin(ang_model)*speed,,-cos(ang_model)*speed gppraytest var,id_box,100 getwork id_box, wx,wy,wz : getwork2 id_box, norm.0, norm.1, norm.2 setpos id_model, wx,wy,wz : setpos id_box, wx,wy+5,wz gpcnvaxis l.0, l.1, l.2, wx,wy,wz : gpcnvaxis l.3, l.4, l.5, wx+norm.0, wy+norm.1, wz+norm.2 ; ★ココが重要------ ; ★アキアキノヒロロさんが発見された画期的な方法に角度を使う fvnorm2ang norm ; ★法線を角度に変換する術(クォータニオンは使わない方法で) setangy id_model, norm.0, norm.1, norm.2 addang id_model, 0, -norm.1, 0 addang id_model, 0, ang_model, 0 ; ★---------------- redraw 0 : gpdraw : rgbcolor $FF00FF : line l.0, l.1, l.3, l.4 : redraw 1 : await 16 goto *main



アキアキノヒロロ

リンク

2024/4/20(Sat) 18:34:57|NO.101577

usagiさん、最後の最後まで、本当にありがとうございます。

>★ココまでは気にしない

プログラミングを始めたころ、
「これは魔法の言葉で、これを書いておけば、勝手にやってくれます。
考え込まないで、大丈夫ですよ。」
なんていう解説があったのを思い出しながら、スクリプトを拝見しています。

怖がらずに、使い倒させていただこうと思います m(>__<)m
またどこかでお会いするのを楽しみにして
それでは、さようなら。



記事削除

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

NO.101521への返信

マスコット

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

名前

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

削除用パスワード

解決したら質問者本人がここをチェックしてください。

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

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