Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VRMSpringBoneを布モノに適用すると突き抜けてしまう #83

Open
ROSTOCK4421195 opened this issue Aug 6, 2018 · 8 comments

Comments

@ROSTOCK4421195
Copy link

VRMSpringBoneをスカートに適用してみたのですが、ボーンの間隔がひろがって衝突判定のコライダの横をすり抜けてしまいしまいます。ボーンに回転制限を設定できるようにできないでしょうか?
https://twitter.com/ROSTOCK_SP/status/1026457279694954497
https://twitter.com/ROSTOCK_SP/status/1026459877315555328

@ousttrue
Copy link
Contributor

ousttrue commented Aug 7, 2018

スプリングとスプリングの間に当たり判定付きのボーンが割り込んでしまうのは、なんらかの方法で対策したいと思います。

@ROSTOCK4421195
Copy link
Author

よろしくお願いいたします。

@hiroj hiroj transferred this issue from vrm-c/UniVRM Dec 18, 2019
@0b5vr
Copy link
Contributor

0b5vr commented Dec 20, 2019

Ref: #96

@hiroj
Copy link
Contributor

hiroj commented May 11, 2020

#90
こちらのClothライブラリをスカート用途で使用できないか検討中です。

@0b5vr 0b5vr changed the title VRMSpringBoneについて VRMSpringBoneを布モノに適用すると突き抜けてしまう May 21, 2020
@0b5vr
Copy link
Contributor

0b5vr commented May 21, 2020

#96 とは別の解決手法がある可能性を鑑み、このissueは #96 とは関係なく開けてお居たほうが良さそうと思います。

@TokageItLab
Copy link

TokageItLab commented Jan 17, 2021

Cloth とは別で回転の角度制限があるとメカ物のヒンジジョイントのような表現が可能となるので、 SpringBone への角度制限の実装を同じく希望します。

ただし、現在の VRM がローカル方向を破棄する以上 SpringBone は仮想ボーンを利用しているのに近い形ですので、例えばスカートのような放射状のボーンで Z 軸回転が起こらなくなるように制限したい時に、全てのスカートの骨が前後にしか揺れなくなる方向推定した軸基準でしか制限ができないというような事が予想されます(※1)。もし SpringBone が現在の実装を引き継ぐのであれば、 SpringBone のパラメータとして角度制限の項目に加え、仮想ボーンのロール値を設定するような(※2)項目を実装する事で任意の方向への角度制限が実現できるのではないかと考えられますが、節ごとに再設定が必要な実装は如何なものかと思います。


※1: 未検証です、間違っていたらすみません。多分ワールド軸であれば座標変換は必要だけど制限できるかも。
※2: 例えばスカートの骨が 8 方向ある場合、斜めなら45°、横側なら 90° とすれば全て X 軸の制限のみで放射状に動かせるのではないでしょうか。

@ghost
Copy link

ghost commented Jan 16, 2023

VRM1がリリースされたため、各ボーンがローカル軸を持つことが可能となったため
SpringBoneに角度制限機能の実装を再び再考していただければと思います。

以下は、UnityChanSpringBone2による角度制限によるスカートのめり込み回避のデモです。

角度制限設定前(ボーンの間からコライダーをすり抜け大きく脚が突き出てしまっている)

UnityChanSpringBone2_.mp4

角度制限設定後(特定の角度より曲がらないように設定したため足が貫通することなく揺れている)

UnityChanSpringBone2_.mp4

角度制限については、UnityChanSpringBone2のソースを見れば実装が分かりますが解説などは以下のUniteの動画を参考にして頂ければと思います。(既にご覧になったことはあると思いますが一応)
https://learning.unity3d.jp/668/

https://github.com/unity3d-jp/UnityChanSpringBone

@0b5vr 0b5vr moved this to To do in VRM Working Group Aug 5, 2024
@TokageItLab
Copy link

TokageItLab commented Jan 10, 2025

角度制限について、個人的にいくつか実験を行ないましたが、範囲制限を行なうにあたっては考慮すべき事項がかなり多くなるように思えました。

  • 範囲を楕円にするのか
    • この場合、パラメータは制限角度と軸とアス比の3つを持つのか、またそれを全てのジョイントにセットするのか
  • どこで制限を行なうのか
    • 各コリジョンの移動後に行なうのか
    • 計算量が多くなりすぎないか
  • 制限を超えそうな時に減衰などが欲しくならないか
  • 範囲外で軸が反転したときの補完をどうするのか
    • 何も考慮せずに移動結果とレストとの dot 積などから制限を行なう場合、移動速度によってはジョイントがワープする可能性があります
    • (参考:Angle limitation)Implement LookAtModifier3D godotengine/godot#98446
    • 制限範囲を跨がないために仮想的なコリジョンのようなものを想定するなど、何らかの処理が必要そう

ただし、範囲での制限ではなく回転軸を固定する場合は比較的簡単な実装が可能であるように感じました。

例えば、X軸回転のみを許可する場合、以下のように各移動と長さ制限の間に、ポイントをローカルYZ平面へスナップする実装を追加するだけです。

Vector3 SpringBoneSimulator3D::snap_position_to_plane(const Transform3D &p_rest, RotationAxis p_axis, const Vector3 &p_position) {
	if (p_axis == ROTATION_AXIS_ALL) {
		return p_position;
	}
	Vector3 result = p_position;
	result = p_rest.affine_inverse().xform(result);
	result[(int)p_axis] = 0; // X = 0, Y = 1, Z = 2, All = 3 (but already aborted in the first line)
	result = p_rest.xform(result);
	return result;
}
// Integration of velocity by verlet.
Vector3 next_tail = verlet->current_tail +
					(verlet->current_tail - verlet->prev_tail) * (1.0 - p_joints[i]->drag) +
					center_transform.basis.get_rotation_quaternion().xform(current_rot.xform(verlet->forward_vector * (p_joints[i]->stiffness * p_delta)) + external);
// Snap to plane if axis is locked.
next_tail = snap_position_to_plane(current_world_pose, p_joints[i]->rotation_axis, next_tail);
// Limit bone length.
next_tail = limit_length(current_origin, next_tail, verlet->length);

// Collision movement.
for (uint32_t j = 0; j < p_collisions.size(); j++) {
	Object *obj = ObjectDB::get_instance(p_collisions[j]);
	if (!obj) {
		continue;
	}
	SpringBoneCollision3D *col = Object::cast_to<SpringBoneCollision3D>(obj);
	if (col) {
		next_tail = col->collide(current_origin, p_joints[i]->radius, verlet->length, next_tail);
		// Snap to plane if axis is locked.
		// This may result in a little penetration of the collision,
		// but it should not be much different from having multiple collisions.
		next_tail = snap_position_to_plane(current_world_pose, p_joints[i]->rotation_axis, next_tail);
		// Limit bone length.
		next_tail = limit_length(current_origin, next_tail, verlet->length);
	}
}
hinge.mp4

各ジョイントに対してそれを設定する場合でも、Enum(X, Y, Z, All)として1つのintパラメータを追加するだけであり、また計算量もそれほど多くありません。(回転軸と前方軸が平行になる事を避けるためのチェックは必要かもしれませんが、静的なチェックで問題ないためパフォーマンスには影響ない筈です)

また、仮に範囲制限を実装するとしても、これは共存可能な実装のはずで、軸固定回転の前後で範囲指定を行なうことは可能だと考えます。回転軸の固定のために指定範囲の楕円のアス比を無限にする訳にもいかない筈なので...。

回転軸の固定によるスカートの貫通対策は DynamicBone でもよく用いられる方法であるため、とりあえず回転軸の固定だけでも実装を検討できないでしょうか。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: To do
Development

No branches or pull requests

5 participants