HDTに対応している装備の揺れ方をカスタマイズする

体型・装備

ヒラヒラ動くスカートの揺れ方を調整してみます。

今回はSimple Skirt (HDT-SMP PHYSICS)を使います。

設定ファイルの場所

設定ファイルは以下になります。

SKSE\Plugins\hdtSkinnedMeshConfigs\OK_Skirt.xml

今回はこのファイルがひとつだけなのでわかりやすいですが、たくさんある場合はメッシュ(nifファイル)に書かれている設定ファイルのパスを確認するといいです。

XMLファイルの編集について

XML形式とは、データの羅列を人間が読みやすいようにしたものです。とはいえ、そのまま読むのは少々辛いので、ツールを使いこなしましょう。

編集ツールはたくさんあると思いますが、Sublime Textのような色付けしてくれるテキストエディタを使うといいと思います。折り畳みで見やすくすることもできます。

機械的に整理すると読みやすくなります。無料で整理してくれるサイトもありますので活用します。

コメントアウトを使うと、設定を一時的に変更して元に戻すのが楽になります。しかもSublime Textなら色が付いてとてもわかりやすいです。

こういった便利なツールを使うようにして、メモ帳を使うのはやめましょう。

ゲームでの確認の仕方

設定ファイルを編集したら、Skyrimでコンソールを開いて以下のコマンドを実行すると反映されます。Skyrimを再起動する必要はありません。

smp reset

これを知っているだけで調整にかかる時間を大幅に短縮できます。

HDT SMP Windを使っている場合、まずは室内の無風状態で調整しましょう。できればHDT-SMPに切り替えるか、HDT SMP Windの設定ファイルでwind機能を無効にしましょう。

設定ファイルの基本

私が整理したSimple Skirt用設定ファイルです。以下の解説のひな型になります。

Simple SkirtのHDT-SMP設定ファイル (xml)

<?xml version="1.0" encoding="UTF-8"?>
<system xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="description.xsd">

    <!-- 以下のボーンは設定なし -->

    <!-- 身体のボーン -->
    <bone name="R Breast01"/>
    <bone name="L Breast01"/>
    <bone name="R Breast02"/>
    <bone name="L Breast02"/>
    <bone name="R Breast03"/>
    <bone name="L Breast03"/>
    <bone name="NPC L Breast"/>
    <bone name="NPC R Breast"/>
    <bone name="NPC L Breast01"/>
    <bone name="NPC R Breast01"/>
    <bone name="NPC L Clavicle [LClv]"/>
    <bone name="NPC R Clavicle [RClv]"/>
    <bone name="NPC L Forearm [LLar]"/>
    <bone name="NPC R Forearm [RLar]"/>
    <bone name="NPC L ForearmTwist1 [LLt1]"/>
    <bone name="NPC R ForearmTwist1 [RLt1]"/>
    <bone name="NPC L ForearmTwist2 [LLt2]"/>
    <bone name="NPC R ForearmTwist2 [RLt2]"/>
    <bone name="NPC L UpperArm [LUar]"/>
    <bone name="NPC R UpperArm [RUar]"/>
    <bone name="NPC L UpperarmTwist1 [LUt1]"/>
    <bone name="NPC R UpperarmTwist1 [RUt1]"/>
    <bone name="NPC L UpperarmTwist2 [LUt2]"/>
    <bone name="NPC R UpperarmTwist2 [RUt2]"/>
    <bone name="NPC L Thigh [LThg]"/>
    <bone name="NPC R Thigh [RThg]"/>
    <bone name="NPC L Calf [LClf]"/>
    <bone name="NPC R Calf [RClf]"/>
    <bone name="NPC R RearCalf [RrClf]"/>
    <bone name="NPC L RearCalf [LrClf]"/>
    <bone name="NPC L FrontThigh"/>
    <bone name="NPC R FrontThigh"/>
    <bone name="NPC L RearThigh"/>
    <bone name="NPC R RearThigh"/>
    <bone name="NPC L Butt"/>
    <bone name="NPC R Butt"/>
    <bone name="NPC L Pussy02"/>
    <bone name="NPC R Pussy02"/>
    <bone name="NPC L Hand [LHnd]"/>
    <bone name="NPC R Hand [RHnd]"/>
    <bone name="NPC RT Anus2"/>
    <bone name="NPC LT Anus2"/>
    <bone name="NPC LB Anus2"/>
    <bone name="NPC RB Anus2"/>
    <bone name="NPC Head [Head]"/>
    <bone name="NPC Pelvis [Pelv]"/>
    <bone name="NPC Spine [Spn0]"/>
    <bone name="NPC Spine2 [Spn2]"/>
    <bone name="NPC Spine1 [Spn1]"/>
    <bone name="NPC Belly"/>
    <bone name="Clitoral1"/>
    <bone name="VaginaDeep1"/>

    <!-- スカートのボーン(一番上の腰の部分) -->
    <bone name="Dress Left F 1" />
    <bone name="Dress Left B 1" />
    <bone name="Dress Right F 1" />
    <bone name="Dress Right B 1" />

    <!-- 以下のボーンの設定 -->
    <bone-default>
        <mass>2</mass>
        <inertia x="25" y="25" z="25" />
        <centerOfMassTransform>
            <basis x="0" y="0" z="0" w="1" />
            <origin x="0" y="0" z="0" />
        </centerOfMassTransform>
        <linearDamping>0.9</linearDamping>
        <angularDamping>0.9</angularDamping>
        <friction>0.1</friction>
        <rollingFriction>0.5</rollingFriction>
        <restitution>0.5</restitution>
        <margin-multiplier>1</margin-multiplier>
    </bone-default>

    <!-- スカートのボーン(2番目以降、裾にむかって2~5) -->
    <bone name="Dress Left F 2" />
    <bone name="Dress Left F 3" />
    <bone name="Dress Left F 4" />
    <bone name="Dress Left F 5" />
    <bone name="Dress Left B 2" />
    <bone name="Dress Left B 3" />
    <bone name="Dress Left B 4" />
    <bone name="Dress Left B 5" />
    <bone name="Dress Right F 2" />
    <bone name="Dress Right F 3" />
    <bone name="Dress Right F 4" />
    <bone name="Dress Right F 5" />
    <bone name="Dress Right B 2" />
    <bone name="Dress Right B 3" />
    <bone name="Dress Right B 4" />
    <bone name="Dress Right B 5" />

    <!-- 仮想地面のshape -->
    <per-triangle-shape name="VirtualGround">
        <margin>0.5</margin>
        <prenetration>10</prenetration>
        <tag>ground</tag>
        <no-collide-with-tag>ground</no-collide-with-tag>
    </per-triangle-shape>

    <!-- 太もも衝突判定用のshape -->
    <per-triangle-shape name="CollisionLegs">
        <margin>0.1</margin>
        <penetration>0.5</penetration>
        <tag>legs</tag>
        <no-collide-with-tag>legs</no-collide-with-tag>
    </per-triangle-shape>

    <!-- スカートのshape -->
    <per-triangle-shape name="skirt">
        <margin>0.1</margin>
        <penetration>0</penetration>
        <tag>skirt</tag>
        <no-collide-with-tag>skirt</no-collide-with-tag>
    </per-triangle-shape>

    <!-- 各ボーンの動きの設定 -->
    <generic-constraint-default>
        <frameInB>
            <basis x="0" y="0" z="0" w="1" />
            <origin x="0" y="0" z="0" />
        </frameInB>
        <useLinearReferenceFrameA>false</useLinearReferenceFrameA>
        <linearLowerLimit x="0" y="0" z="0" />
        <linearUpperLimit x="0" y="0" z="0" />

        <!-- 内向きの可動範囲 -->
        <angularLowerLimit x="-0.04" y="-0.04" z="-0.08" />
        <!-- 外向きの可動範囲 -->
        <angularUpperLimit x="0.04" y="0.26" z="0.08" />

        <linearStiffness x="0" y="0" z="0" />
        <angularStiffness x="0" y="0" z="0" />
        <linearDamping x="0" y="0" z="0" />
        <angularDamping x="0" y="0" z="0" />
        <linearEquilibrium x="0" y="0" z="0" />
        <angularEquilibrium x="0" y="0" z="0" />
    </generic-constraint-default>

    <constraint-group>
        <generic-constraint bodyA="Dress Left B 2" bodyB="Dress Left B 1" />
        <generic-constraint bodyA="Dress Left B 3" bodyB="Dress Left B 2" />
        <generic-constraint bodyA="Dress Left B 4" bodyB="Dress Left B 3" />
        <generic-constraint bodyA="Dress Left B 5" bodyB="Dress Left B 4" />
    </constraint-group>

    <constraint-group>
        <generic-constraint bodyA="Dress Right B 2" bodyB="Dress Right B 1" />
        <generic-constraint bodyA="Dress Right B 3" bodyB="Dress Right B 2" />
        <generic-constraint bodyA="Dress Right B 4" bodyB="Dress Right B 3" />
        <generic-constraint bodyA="Dress Right B 5" bodyB="Dress Right B 4" />
    </constraint-group>

    <constraint-group>
        <generic-constraint bodyA="Dress Left F 2" bodyB="Dress Left F 1" />
        <generic-constraint bodyA="Dress Left F 3" bodyB="Dress Left F 2" />
        <generic-constraint bodyA="Dress Left F 4" bodyB="Dress Left F 3" />
        <generic-constraint bodyA="Dress Left F 5" bodyB="Dress Left F 4" />
    </constraint-group>

    <constraint-group>
        <generic-constraint bodyA="Dress Right F 2" bodyB="Dress Right F 1" />
        <generic-constraint bodyA="Dress Right F 3" bodyB="Dress Right F 2" />
        <generic-constraint bodyA="Dress Right F 4" bodyB="Dress Right F 3" />
        <generic-constraint bodyA="Dress Right F 5" bodyB="Dress Right F 4" />
    </constraint-group>

</system>

bone要素とbone-defaultには順番があります。

  • bone-default要素を定義するとそれ以降に置いたbone要素に反映されます。
  • bone-default要素を定義する前はbone-default要素の個々の値は0になっているようです。
  • bone-default要素を定義する前に置いたbone要素は、個々の値が0に設定されるようです。
  • 定義しなかったbone要素は内容不定(HDT-SMP初期値?)となり、挙動がおかしくなります。

装備のメッシュが持っているbone要素に関してはbone要素を必ず定義しておかないとならないということです。装備のメッシュが持っているbone要素というのは、要するにWeightを塗ったboneということです。例えばCollisionLegsというshapeにCBBE 3BBBの太もものweightを塗って動きを反映させようとした場合、太もものboneの定義を追加する必要があるということです。

使っていないbone要素の定義は単に無視されるだけのようですので、CBBEとCBBE 3BBBのboneを全て列挙しておけばいいと思います。

よくある不具合として、地面に向かってビローンと落ちていく現象がありますが、bone要素を定義していないか、定義する位置を間違えていますので、確認しましょう。

重さをかえる

重さはMassになります。丸い物体なら、Massが小さいと風船のようになり、大きいとボーリング玉のようになります。重さが動き方にそのまま反映されますので、理想の動きをする値に設定しましょう。

スカートのMassは初期値が2になっていました。

<bone-default>
    <mass>2</mass>

スカートが動くタイミングは2つあります。プレイヤーが動いた時と風が吹いたとき(HDT SMP Wind)です。

0.1まで下げると、風が吹いているだけでめくれっぱなしになります。

大きくするとあまり揺れなくなります。重くしすぎるとコリジョンと衝突した時に跳ね返らなくなるので、しゃがんだ時にスカートが太ももにめり込みます。風の影響も小さくなりますので、風で揺らめてほしいなら1.0~2.0の間で調整すればいいのかなと思います。

bone-default要素にMassを書いたので、bone-default要素の後に置いたbone要素に適用されます。個々のbone要素でMassを個別に定義すればボーン毎にMassを設定できると思いますが、そこまでやるのは面倒だったのでやりませんでした。

動く範囲をかえる

動き方は2つあります。移動(linear)と回転(angular)です。Lowerが下限でUpperが上限です。

Lowerがマイナス方向で、Upperがプラス方向です。逆にすると正常に動作しませんので注意してください。

デフォルトはこんな感じです。

<generic-constraint-default>
    <linearLowerLimit x="0" y="0" z="0" />
    <linearUpperLimit x="0" y="0" z="0" />
    <angularLowerLimit x="-0.04" y="-0.04" z="-0.08" />
    <angularUpperLimit x="0.04" y="0.26" z="0.08" />

移動が0で回転だけで動きを表現しているようです。試しに移動をありにして回転を0にしてみましたが、まともに動きませんでした。

y軸のUpperだけが少し大きくなっています。これがスカートが外側に向かって動く範囲になります。

x軸とz軸もわずかに数値が設定されていますが、おそらくはわずかな揺れの動きを実現するためと思います。

さて、私が一番調整したかったのが、めくりあがる高さです。デフォルトの0.26だとめくれすぎると感じます。1まで上げると思いっきりめくれます。0.1であまりあがらなくなりました。

ところが、後ろ側はいいのですが、前もめくれなくなるので、スニークでしゃがんだ時にスカートが太ももに食い込んでしまいます。むしろ、デフォルトの0.26ですら少し食い込んでいました。0.5くらいにあげると良くなりました。でも前に合わせて調整すると、今度は後ろ側がめくれすぎてしまいます。

これはgeneric-constraint-defaultが各ボーンのデフォルト値、つまり前も後ろもgeneric-constraint-defaultの値になっているからです。よって、前と後ろ、上と下でそれぞれ設定をわければいいのです。

ボーン名のLeftが左側でRightが右側、Fが前側でBが後ろ側です。それぞれ高さごとに5個あるので、合計20個のボーンで構成されています。ただし1番は一番上の腰にもっとも近い動かない部分になるので、設定をするのは2~5番です。

<generic-constraint-default>
	<frameInB>
		<basis x="0" y="0" z="0" w="1" />
		<origin x="0" y="0" z="0" />
	</frameInB>
	<useLinearReferenceFrameA>false</useLinearReferenceFrameA>
	<linearLowerLimit x="0" y="0" z="0" />
	<linearUpperLimit x="0" y="0" z="0" />

	<!-- 内向きの可動範囲 -->
	<!--<angularLowerLimit x="-0.04" y="-0.04" z="-0.08" />-->
	<angularLowerLimit x="-0.04" y="-0.5" z="-0.08" />
	<!-- 外向きの可動範囲 -->
	<!--<angularUpperLimit x="0.04" y="0.26" z="0.08" />-->
	<angularUpperLimit x="0.04" y="0.5" z="0.08" />

	<linearStiffness x="0" y="0" z="0" />
	<angularStiffness x="0" y="0" z="0" />
	<linearDamping x="0" y="0" z="0" />
	<angularDamping x="0" y="0" z="0" />
	<linearEquilibrium x="0" y="0" z="0" />
	<angularEquilibrium x="0" y="0" z="0" />
</generic-constraint-default>

<constraint-group>
	<generic-constraint bodyA="Dress Left B 2" bodyB="Dress Left B 1">
		<angularLowerLimit x="-0.04" y="0" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.1" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Left B 3" bodyB="Dress Left B 2">
		<angularLowerLimit x="-0.04" y="-0.05" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.1" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Left B 4" bodyB="Dress Left B 3">
		<angularLowerLimit x="-0.04" y="-0.2" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.05" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Left B 5" bodyB="Dress Left B 4">
		<angularLowerLimit x="-0.04" y="-0.3" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.05" z="0.08" />
	</generic-constraint>
</constraint-group>

<constraint-group>
	<generic-constraint bodyA="Dress Right B 2" bodyB="Dress Right B 1">
		<angularLowerLimit x="-0.04" y="0" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.1" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Right B 3" bodyB="Dress Right B 2">
		<angularLowerLimit x="-0.04" y="-0.05" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.1" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Right B 4" bodyB="Dress Right B 3">
		<angularLowerLimit x="-0.04" y="-0.2" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.05" z="0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Right B 5" bodyB="Dress Right B 4">
		<angularLowerLimit x="-0.04" y="-0.3" z="-0.08" />
		<angularUpperLimit x="0.04" y="0.05" z="0.08" />
	</generic-constraint>
</constraint-group>

<constraint-group>
	<generic-constraint bodyA="Dress Left F 2" bodyB="Dress Left F 1">
		<angularLowerLimit x="-0.04" y="0" z="-0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Left F 3" bodyB="Dress Left F 2" />
	<generic-constraint bodyA="Dress Left F 4" bodyB="Dress Left F 3" />
	<generic-constraint bodyA="Dress Left F 5" bodyB="Dress Left F 4" />
</constraint-group>

<constraint-group>
	<generic-constraint bodyA="Dress Right F 2" bodyB="Dress Right F 1">
		<angularLowerLimit x="-0.04" y="0" z="-0.08" />
	</generic-constraint>
	<generic-constraint bodyA="Dress Right F 3" bodyB="Dress Right F 2" />
	<generic-constraint bodyA="Dress Right F 4" bodyB="Dress Right F 3" />
	<generic-constraint bodyA="Dress Right F 5" bodyB="Dress Right F 4" />
</constraint-group>

衝突(コリジョン)の範囲をかえる

太ももの周りに衝突判定を加えるShapeがあります。これが太すぎるので、しゃがんだ時などにスカートが浮いてしまいます。なぜこうしてあるのかは不明ですが、おそらく立った状態でもある程度は広がるようにするためなのかもしれません。

へこましツールで太ももの形状と同じになるまで縮めたら、しゃがんでもスカートが浮かなくなりました。

逆にもっと浮かせたいのであれば、marginを大きくすればいいです。コリジョンというのは、目に見えるshapeの周りに目に見えないバリアがあるというイメージです。marginを大きくするとバリアの範囲が広がるので、shapeとshapeの間に出来る隙間が大きくなります。

<per-triangle-shape name="CollisionLegs">
    <margin>0.1</margin>
    <penetration>0.5</penetration>
    <tag>legs</tag>
    <no-collide-with-tag>legs</no-collide-with-tag>
</per-triangle-shape>

動きに関する原則

まず、shapeは可動範囲を超えて動きません。例えば、可動範囲が0の場合、コリジョンの範囲をいくら調整してもshapeが可動しないのでshapeは動きません。つぎに、可動範囲の中でコリジョンの衝突判定が行われます。

スニークした時にスカートの前の部分が太ももに食い込んでしまうケースを考えてみます。まず、スカートの前の部分の外向きにたいする可動範囲を大きくします。そもそも可動範囲が狭ければスカートが上に上がらないのでどうしても食い込みます。それから太ももにあるコリジョンとの衝突範囲を調整します。

タイトルとURLをコピーしました