diff --git a/archive/Readme.txt b/archive/Readme.txt index 6bc5e99..63efaa9 100644 --- a/archive/Readme.txt +++ b/archive/Readme.txt @@ -3,7 +3,7 @@  「PmxTailor ローカル版」 -  ver2.00.03 +  ver2.01.00                  miu200521358 @@ -49,7 +49,7 @@ https://youtu.be/aQ70AHE8Rdo ■ 同梱ファイル ---------------------------------------------------------------- - ・PmxTailor2.00.00.exe   … ツール本体(言語別ショートカットあり) + ・PmxTailor2.01.00.exe   … ツール本体(言語別ショートカットあり)  ・Readme.txt        … リドミ  ・VMDサイジングWiki     … Wikiへのリンク  ・コンテンツツリー用静画  … コンテンツツリー用静画へのリンク @@ -217,6 +217,24 @@ https://github.com/miu200521358/pmx_tailor ■ 履歴 ---------------------------------------------------------------- +ver2.01.00(2023/02/18) +■機能追加・修正 + ・メッシュ走査・ボーンマッピングロジック変更 + ・物理パラ調整 +  ・プリセットも調整 +  ・プリセット「ウール」を追加 + ・不定形なメッシュ用に特殊形状「面欠け」追加 + ・ジョイントの位置を「ボーン位置」に置くように変更 +  ・パラ調整(詳細)画面の詳細オプションから従来の「ボーン間」に変更可 + ・モデルコメントに指定したパラ全ての情報を出力するよう追加 + ・ジョイントの横移動制限をボーンの距離に合わせた量に計算するよう修正 +■不具合修正 + ・下部エッジを検出する際の閾値が全体の中央値になっていたので、上部エッジの中央値に修正 + ・縦ジョイントがなかった場合のログを、根元とそれ以降でメッセージを分けるよう修正 + ・剛体の向きがおかしくなる場合があるのを修正 + ・ウェイト二度塗りを避けるよう、ウェイト塗りの順番を修正 + ・再利用で一列だけで布プリセットを使用した場合、横を強制的に参照しようとしてエラーになっていたのを修正 + ver2.00.03(2022/11/19) ■機能追加  ・選択されたメッシュの真ん中にのみボーンを張る「密度基準:中央」を追加 diff --git "a/archive/\316\262\347\211\210Readme.txt" "b/archive/\316\262\347\211\210Readme.txt" index 6758e5a..b17c3bb 100644 --- "a/archive/\316\262\347\211\210Readme.txt" +++ "b/archive/\316\262\347\211\210Readme.txt" @@ -16,20 +16,11 @@  ・ニコニコミュニティ「miuの実験室」    https://com.nicovideo.jp/community/co5387214 - ・ディスコード「MMDの集い DISCORD支部」 + ・ディスコード「MMDの集い Discord支部」 +   https://discord.gg/wBcwFreHJ8  ※基本的にβ版は上記二箇所でのみ配布しておりますので、上記以外で見かけたらお手数ですがご連絡下さい。 ----------------------------------------------------------------- -■ 同梱モデルについて ----------------------------------------------------------------- - -・マネキン素体は、ささやか様よりお借りしています - https://www.nicovideo.jp/watch/sm32890648 - -・スカートはBlender自作(テクスチャはBlenderプリセット)です - 物理設定のテスト用にお使いください - ---------------------------------------------------------------- ■ β版をご利用いただくにあたってのお願い ---------------------------------------------------------------- @@ -61,6 +52,99 @@ ■ rivision ---------------------------------------------------------------- +PmxTailor_2.01.00_β09 (2023/02/13) +・再利用で一列だけで布プリセットを使用した場合、横を強制的に参照しようとしてエラーになっていたのを修正 + +PmxTailor_2.01.00_β08 (2023/02/13) +・横優先の並び順が戻し切れてなかったので修正 +・頂点マップが一列だった場合に縦方向の距離が取れておらず、ウェイトが塗れてなかったのを修正 + +PmxTailor_2.01.00_β07 (2023/02/12) +・胸物理のパラ調整 +・折り返し剛体の大きさや位置などを、ひとつ前の剛体と合わせるよう修正 +・折り返し剛体の生成判定が間違っていたので修正 +・仮想エッジを作った場合、その結果としてエッジではなくなった辺がある場合、除外するよう修正 + ・エッジを辿った際に意図せぬ箇所で走査処理が終了してしまう +・ひとつ先の仮想頂点を取得する際に、自分以降の条件が抜けていたのを修正 + +PmxTailor_2.01.00_β06 (2023/02/12) +・残ウェイトに渡す頂点INDEXリストの保持方法を修正 +・末端ボーンの登録FLGがONにならない場合を修正(ボーン密度からの計算が一部ミスってた) +・同一最上部キーで分けた時に、スリットの途中の辺が一辺だけ抽出されるのを除外 + ・面欠けの辺が一辺だけのとき正常に抽出できない +・ボーンのマッピングを修正 + ・X軸方向に欠けてる箇所の抽出が間違っていた(縦に不要なボーンが張られていた) +・円周の最後の頂点ウェイトを塗る際に縦方向の距離が測れて無くてウェイトが0になっていたのを修正 +・Y軸方向のボーン付与FLGを全体のマップを通して同じ箇所にボーンを張れるよう判定処理追加 +・一枚布の横末端の剛体を折り返しで作成するよう機能追加 +・親剛体制限をデフォルトFALSEに(制限がキツすぎるので再考) + +PmxTailor_2.01.00_β05 (2023/02/11) +・自身と同じ位置のボーンを親に持つ子ボーンの判定条件を厳しめに変更 + +PmxTailor_2.01.00_β04 (2023/02/11) +・物理のパラ調整 +・ウェイト塗りの順番を修正 + ・マップ頂点→残頂点→グラデ頂点→裏頂点 となっており、二重に不要なウェイトが塗られる場合があった + ・マップ頂点→グラデ頂点→裏頂点→残頂点で塗れるよう修正 +・スリットメッシュで張るボーンのマッピングを修正 +・親ボーンが見つからなかった場合に警告してルートボーンに紐付けて続けるよう修正 + ・大体の場合、不要な非表示ボーン +・ジョイントの順番をボーン・剛体の順番(縦方向)に揃えた +・斜めジョイントのY方向に若干の移動を許可 + +PmxTailor_2.01.00_β03 (2023/02/05) +・Vroid2Pmxインポート物理のパラ調整 + +PmxTailor_2.01.00_β02 (2023/02/05) +・仮登録用ジョイントキーの生成にボーンマップのINDEXが入って無くて上書きされてたのを修正 +・バネの計算数式を修正 + +PmxTailor_2.01.00_β01 (2023/02/05) +・ジョイントの位置のデフォルト設定をボーン位置に変更 + ・その方が荒いメッシュで安定しやすい +・面抜け→面欠けにパラメーター名変更 +・複数マップの際にボーンの張り方フラグをひとつ前の頂点マップを参照して決めるよう修正 +・スライダーによるジョイント制限値の算出式を変更 + ・ボーン位置の場合、ボーン間より少し柔らかい設定 + ・ジョイントの制限値は「柔らかさ」パラ + ・ジョイントのばねは「張り」パラ +・プリミティブ設定パラを調整 + +PmxTailor_2.00.04_β03 (2023/02/05) +・一頂点だけで繋がっているメッシュを切り分けるよう修正 +・特殊形状「面抜け」追加 + ・抜けがある場合、仮想エッジを張るよう処理追加 +・エッジの検出ルートを変更 + ・一辺(2つの頂点)が見つかってる場合、それと辺が内積が大きいものを選択する +  既存は「X(中央揃え) - Z(降順) - Y(降順)」でソートしたもので大きいものを選択していた +・線分の交差判定を修正 +・割りに応じたボーンの張り方を修正 + ・仮想頂点がある場合、そこは面がある前提でボーンを張る + ・縦軸の末端以降は末端仮想頂点を1つだけ作成して、その後はボーンを張らない + ・メッシュが不定形の場合、それを加味して縦横を張る +・スリットや水平メッシュのウェイト・ボーン・剛体・ジョイントを修正 + +PmxTailor_2.00.04_β02 (2023/01/21) +・髪のジョイントY値を0に変更(捩れないように) +・モデルコメントに指定したパラの出力を追加 +・根元推定:縮尺の処理を理想上の縮尺に合わせた根元を推定するよう変更 + ・デフォルトは角度なので、ほぼ影響はなし +・スリットのボーン生成に失敗する場合があったのを修正 + ・ボーン密度を大きく(荒く)したときに隙間にハマるボーンが生成されなかった + ・切れ目の根元のボーンが片方生成されない場合があったのを修正 +・メッシュの上下を分けるロジックを修正 + ・親ボーンに下半身(親ボーンがメッシュより上)を想定していて、襟など首回りのメッシュで上半身2を親とした場合などに対応できてなかったのを修正 +・剛体の向きがおかしくなる場合があるのを修正 + ・剛体のY軸方向の判定がミスってた + +PmxTailor_2.00.04_β01 (2022/11/30) +・下部エッジを検出する際の閾値が全体の中央値になっていたので、上部エッジの中央値に修正 + (スリットはエッジ区分を分けなくても、角に沿って適宜ボーンが配置されるようになっていたため) +・縦ジョイントがなかった場合のログを、根元とそれ以降でメッセージを分けるよう修正 + (裾がギザギザで縦ジョイントが作れなかった場合には縦ジョイントがなくても問題がないため、 +  警告の仕方を弱めに変更) + PmxTailor_2.00.03_β02 (2022/11/06) ・剛体とジョイントの仮想頂点取得時のチェック追加 ・末端の仮想ボーンを常にメッシュ一行分の幅で生成するよう変更 diff --git a/crumb/ApMikuHair.py b/crumb/ApMikuHair.py new file mode 100644 index 0000000..bb05429 --- /dev/null +++ b/crumb/ApMikuHair.py @@ -0,0 +1,1162 @@ +""" +縺ゅエ繝溘け鬮ェ邏ー蛻蛹 +""" +from datetime import datetime +import sys +import pathlib +import os +import numpy as np +import random +from glob import glob +import math + +# 縺薙ョ繧ス繝シ繧ケ縺ョ縺ゅk繝繧」繝ャ繧ッ繝医Μ縺ョ邨カ蟇セ繝代せ繧貞叙蠕 +current_dir = pathlib.Path(__file__).resolve().parent +# 繝「繧ク繝・繝シ繝ォ縺ョ縺ゅk繝代せ繧定ソス蜉 +sys.path.append(str(current_dir) + "/../") +sys.path.append(str(current_dir) + "/../src/") + +from mmd.PmxReader import PmxReader # noqa +from mmd.VmdReader import VmdReader # noqa +from mmd.VmdWriter import VmdWriter # noqa +from mmd.PmxWriter import PmxWriter # noqa +from mmd.PmxData import ( + PmxModel, + Vertex, + Material, + Bone, + Morph, + DisplaySlot, + RigidBody, + Joint, + Bdef1, + Bdef2, + Bdef4, +) # noqa +from mmd.VmdData import ( + VmdMotion, + VmdBoneFrame, + VmdCameraFrame, + VmdInfoIk, + VmdLightFrame, + VmdMorphFrame, + VmdShadowFrame, + VmdShowIkFrame, +) # noqa +from module.MMath import MRect, MVector2D, MVector3D, MVector4D, MQuaternion, MMatrix4x4 # noqa +from module.MOptions import MOptionsDataSet # noqa +from module.MParams import BoneLinks # noqa +from utils import MBezierUtils, MServiceUtils # noqa +from utils.MException import SizingException # noqa +from utils.MLogger import MLogger # noqa +from service.PmxTailorExportService import read_vertices_from_file, VirtualVertex, calc_ratio + + +MLogger.initialize(level=MLogger.DEBUG, is_file=True) +logger = MLogger(__name__, level=MLogger.DEBUG) + + +def exec_joint(): + model = PmxReader( + "E:/MMD/MikuMikuDance_v926x64/Work/202101_vroid/_蝣ア蜻/繝ゥ繝ッ繧、繝ォ1223/APmiku_nakedhair_IKx_onlyee_4_20221224_152739_20221224_165809_strong.pmx", + is_check=False, + is_sizing=False, + ).read_data() + print(model.name) + + right_bone_name1 = [ + "蜿ウ鬮ェ1荳ュ蠢", + "蜿ウ鬮ェ1-007", + "蜿ウ鬮ェ1-011", + "蜿ウ鬮ェ1-015", + "蜿ウ鬮ェ1-019", + "蜿ウ鬮ェ1-023", + "蜿ウ鬮ェ1-027", + "蜿ウ鬮ェ1-031", + "蜿ウ鬮ェ1-035", + # "蜿ウ鬮ェ1-039", + # "蜿ウ鬮ェ1-043", + # "蜿ウ鬮ェ1-047", + # "蜿ウ鬮ェ1-051", + # "蜿ウ鬮ェ1-055", + ] + right_bone_name2 = [ + "蜿ウ鬮ェ2荳ュ蠢", + "蜿ウ鬮ェ2-003", + "蜿ウ鬮ェ2-007", + "蜿ウ鬮ェ2-011", + "蜿ウ鬮ェ2-015", + "蜿ウ鬮ェ2-019", + "蜿ウ鬮ェ2-023", + "蜿ウ鬮ェ2-027", + "蜿ウ鬮ェ2-031", + # "蜿ウ鬮ェ2-035", + # "蜿ウ鬮ェ2-039", + # "蜿ウ鬮ェ2-043", + # "蜿ウ鬮ェ2-047", + # "蜿ウ鬮ェ2-051", + ] + right_bone_name3 = [ + "蜿ウ鬮ェ3荳ュ蠢", + "蜿ウ鬮ェ3-007", + "蜿ウ鬮ェ3-011", + "蜿ウ鬮ェ3-015", + "蜿ウ鬮ェ3-019", + "蜿ウ鬮ェ3-023", + "蜿ウ鬮ェ3-027", + "蜿ウ鬮ェ3-031", + "蜿ウ鬮ェ3-035", + # "蜿ウ鬮ェ3-039", + # "蜿ウ鬮ェ3-043", + # "蜿ウ鬮ェ3-047", + ] + + left_bone_name1 = [ + "蟾ヲ鬮ェ1荳ュ蠢", + "蟾ヲ鬮ェ1-007", + "蟾ヲ鬮ェ1-011", + "蟾ヲ鬮ェ1-015", + "蟾ヲ鬮ェ1-019", + "蟾ヲ鬮ェ1-023", + "蟾ヲ鬮ェ1-027", + "蟾ヲ鬮ェ1-031", + "蟾ヲ鬮ェ1-035", + # "蟾ヲ鬮ェ1-039", + # "蟾ヲ鬮ェ1-043", + # "蟾ヲ鬮ェ1-047", + # "蟾ヲ鬮ェ1-051", + # "蟾ヲ鬮ェ1-055", + ] + left_bone_name2 = [ + "蟾ヲ鬮ェ2荳ュ蠢", + "蟾ヲ鬮ェ2-005", + "蟾ヲ鬮ェ2-009", + "蟾ヲ鬮ェ2-013", + "蟾ヲ鬮ェ2-017", + "蟾ヲ鬮ェ2-021", + "蟾ヲ鬮ェ2-025", + "蟾ヲ鬮ェ2-029", + "蟾ヲ鬮ェ2-033", + # "蟾ヲ鬮ェ2-037", + # "蟾ヲ鬮ェ2-041", + # "蟾ヲ鬮ェ2-045", + # "蟾ヲ鬮ェ2-049", + # "蟾ヲ鬮ェ2-053", + ] + left_bone_name3 = [ + "蟾ヲ鬮ェ3荳ュ蠢", + "蟾ヲ鬮ェ3-010", + "蟾ヲ鬮ェ3-014", + "蟾ヲ鬮ェ3-018", + "蟾ヲ鬮ェ3-022", + "蟾ヲ鬮ェ3-026", + "蟾ヲ鬮ェ3-030", + "蟾ヲ鬮ェ3-034", + "蟾ヲ鬮ェ3-038", + # "蟾ヲ鬮ェ3-042", + # "蟾ヲ鬮ェ3-046", + # "蟾ヲ鬮ェ3-050", + ] + + for bone_names in [ + zip(right_bone_name1, right_bone_name1[1:], right_bone_name2, right_bone_name2[1:]), + zip(right_bone_name2, right_bone_name2[1:], right_bone_name3, right_bone_name3[1:]), + zip(right_bone_name3, right_bone_name3[1:], right_bone_name1, right_bone_name1[1:]), + zip(left_bone_name1, left_bone_name1[1:], left_bone_name2, left_bone_name2[1:]), + zip(left_bone_name2, left_bone_name2[1:], left_bone_name3, left_bone_name3[1:]), + zip(left_bone_name3, left_bone_name3[1:], left_bone_name1, left_bone_name1[1:]), + ]: + for n, (a_bone_from_name, a_bone_to_name, b_bone_from_name, b_bone_to_name) in enumerate(bone_names): + a_bone_from = model.bones[a_bone_from_name] + a_bone_to = model.bones[a_bone_to_name] + b_bone_from = model.bones[b_bone_from_name] + b_bone_to = model.bones[b_bone_to_name] + + horizontal_joint = build_joint(model, a_bone_from, a_bone_to, b_bone_from, b_bone_to, "竊", n) + # reverse_joint = build_joint(model, b_bone_from, b_bone_to, a_bone_from, a_bone_to, "竊") + + model.joints[horizontal_joint.name] = horizontal_joint + # model.joints[reverse_joint.name] = reverse_joint + + PmxWriter().write( + model, + f"E:/MMD/MikuMikuDance_v926x64/Work/202101_vroid/_蝣ア蜻/繝ゥ繝ッ繧、繝ォ1223/APmiku_nakedhair_IKx_onlyee_4_20221224_152739_20221224_165809_strong_{datetime.now():%Y%m%d_%H%M%S}.pmx", + ) + + +def build_joint( + model: PmxModel, + a_bone_from: Bone, + a_bone_to: Bone, + b_bone_from: Bone, + b_bone_to: Bone, + direction_mark: str, + limit: float, +): + # 蜑帑ス -------- + a_rigidbody = model.rigidbodies[a_bone_to.name] + b_rigidbody = model.rigidbodies[b_bone_to.name] + + # 蜑帑ス薙ョZ霆ク譁ケ蜷代r豎ゅa繧 ----- + a_x_direction_from_pos = a_y_direction_from_pos = a_bone_from.position + a_x_direction_to_pos = a_bone_to.position + a_y_direction_to_pos = a_y_direction_from_pos + MVector3D(1, 0, 0) + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + a_x_direction_pos = (a_x_direction_to_pos - a_x_direction_from_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) + a_y_direction_pos = (a_y_direction_to_pos - a_y_direction_from_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) + a_z_direction_pos = MVector3D.crossProduct(a_x_direction_pos, a_y_direction_pos) + + # -------- + b_x_direction_from_pos = b_y_direction_from_pos = b_bone_from.position + b_x_direction_to_pos = b_bone_to.position + b_y_direction_to_pos = b_y_direction_from_pos + MVector3D(1, 0, 0) + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + b_x_direction_pos = (b_x_direction_to_pos - b_x_direction_from_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) + b_y_direction_pos = (b_y_direction_to_pos - b_y_direction_from_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) + b_z_direction_pos = MVector3D.crossProduct(b_x_direction_pos, b_y_direction_pos) + # -------- + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + x_direction_pos = (b_bone_to.position - a_bone_to.position).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) + z_direction_pos = ((a_z_direction_pos + b_z_direction_pos) / 2).normalized() + joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) + joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + + joint_name = f"{direction_mark}|{a_rigidbody.name}|{b_rigidbody.name}" + + joint_euler = joint_qq.toEulerAngles() + joint_rotation_radians = MVector3D( + math.radians(joint_euler.x()), math.radians(joint_euler.y()), math.radians(joint_euler.z()) + ) + + return Joint( + joint_name, + joint_name, + 0, + a_rigidbody.index, + b_rigidbody.index, + b_bone_to.position, + joint_rotation_radians, + MVector3D(0, -0.1 * (limit**1.2), 0), + MVector3D(0, 0.1 * (limit**1.2), 0), + MVector3D(), + MVector3D(), + MVector3D(), + MVector3D(), + ) + + +def exec(): + model = PmxReader( + "E:/MMD/MikuMikuDance_v926x64/Work/202101_vroid/_蝣ア蜻/繝ゥ繝ッ繧、繝ォ1223/APmiku_nakedhair_IKx_onlyee_start.pmx", + is_check=False, + is_sizing=False, + ).read_data() + print(model.name) + + for csv_file_path in glob("E:/MMD/MikuMikuDance_v926x64/Work/202101_vroid/_蝣ア蜻/繝ゥ繝ッ繧、繝ォ1223/*.csv"): + abb_name = os.path.basename(csv_file_path.replace(".csv", "")) + target_vertices = read_vertices_from_file(csv_file_path, model, "鬮ェ") + + params = {} + # 邁。譏鍋沿繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ ------------- + params["material_name"] = "鬮ェ" + params["back_material_name"] = "" + params["back_extend_material_names"] = [] + params["edge_material_name"] = "" + params["edge_extend_material_names"] = [] + params["parent_bone_name"] = "鬆ュ" + params["abb_name"] = abb_name + params["direction"] = "荳" + params["exist_physics_clear"] = "縺吶∋縺ヲ陦ィ髱「" + params["special_shape"] = "縺ェ縺" + params["vertices_csv"] = "" + params["vertices_edge_csv"] = "" + params["vertices_back_csv"] = "" + params["top_vertices_csv"] = "" + params["mass"] = 0 + params["air_resistance"] = 0 + params["shape_maintenance"] = 0 + params["vertical_bone_density"] = 4 + + vertex_map, virtual_vertices, threshold, max_pos, remaining_vertices = create_vertex_map( + model, params, params["material_name"], target_vertices + ) + + ( + root_bone, + virtual_vertices, + registered_bones, + bone_vertical_distances, + bone_horizonal_distances, + bone_connected, + root_yidx, + ) = create_bone(model, params, params["material_name"], virtual_vertices, vertex_map, threshold, max_pos) + + remaining_vertices = create_weight( + model, + virtual_vertices, + vertex_map, + registered_bones, + bone_vertical_distances, + root_yidx, + remaining_vertices, + ) + + create_remaining_weight(model, virtual_vertices, vertex_map, remaining_vertices) + + PmxWriter().write( + model, + f"E:/MMD/MikuMikuDance_v926x64/Work/202101_vroid/_蝣ア蜻/繝ゥ繝ッ繧、繝ォ1223/APmiku_nakedhair_IKx_onlyee_{params['vertical_bone_density']}_{datetime.now():%Y%m%d_%H%M%S}.pmx", + ) + + +def get_rigidbody(model: PmxModel, bone_name: str): + if bone_name not in model.bones: + return None + + for rigidbody in model.rigidbodies.values(): + if rigidbody.bone_index == model.bones[bone_name].index: + return rigidbody + + return None + + +def create_remaining_weight( + model: PmxModel, + virtual_vertices: dict, + vertex_map: np.ndarray, + remaining_vertices: dict, +): + # 繧ヲ繧ァ繧、繝亥。励j邨ゅo縺」縺溷ョ滄らせ繝ェ繧ケ繝 + weighted_vidxs = [] + + # 蝪励j邨ゅo縺」縺滄らせ繝ェ繧ケ繝 + weighted_vkeys = list(set(list(virtual_vertices.keys())) - set(list(remaining_vertices.keys()))) + + weighted_poses = {} + for vkey in weighted_vkeys: + vv = virtual_vertices[vkey] + if vv.vidxs(): + weighted_poses[vkey] = vv.position().data() + weighted_vidxs.extend(vv.vidxs()) + + # 逋サ骭イ貂医∩縺ョ繝懊シ繝ウ縺ョ菴咲スョ繝ェ繧ケ繝 + bone_poses = {} + for v_yidx in range(vertex_map.shape[0]): + for v_xidx in range(vertex_map.shape[1]): + if np.isnan(vertex_map[v_yidx, v_xidx]).any(): + continue + + v_key = tuple(vertex_map[v_yidx, v_xidx]) + vv = virtual_vertices[v_key] + + bones = [b for b in vv.map_bones.values() if b] + if bones: + # 繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧句エ蜷医√懊シ繝ウ菴咲スョ繧剃ソ晄戟 + bone_poses[bones[0].index] = bones[0].position.data() + continue + + # 繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺ェ縺邂謇縺九▽縺セ縺繧ヲ繧ァ繧、繝医′蝪励i繧後※縺ェ縺縺ョ縺ッ谿矩らせ縺ォ蜈・繧後k + if v_key not in remaining_vertices and not vv.deform: + remaining_vertices[v_key] = vv + + remain_cnt = len(remaining_vertices) * 2 + while remaining_vertices.items() and remain_cnt > 0: + remain_cnt -= 1 + # 繝ゥ繝ウ繝繝縺ァ驕ク縺カ + vkey = list(remaining_vertices.keys())[random.randrange(len(remaining_vertices))] + vv = remaining_vertices[vkey] + + if not vv.vidxs(): + # vidx 縺後↑縺縺ョ縺ッ縺昴b縺昴b蟇セ雎。螟 + del remaining_vertices[vkey] + continue + + # 繧ヲ繧ァ繧、繝域ク医∩鬆らせ縺ョ縺縺。縲∵怙繧りソ代>縺ョ繧呈歓蜃コ + weighted_diff_distances = np.linalg.norm( + np.array(list(weighted_poses.values())) - vv.position().data(), ord=2, axis=1 + ) + + nearest_vkey = list(weighted_poses.keys())[np.argmin(weighted_diff_distances)] + nearest_vv = virtual_vertices[nearest_vkey] + nearest_deform = nearest_vv.deform + # nearest_vv.connected_vvs.extend(vv.vidxs()) + + if not nearest_vv.deform: + # 繝繝輔か繝シ繝縺ョ蟇セ雎。縺後↑縺蝣エ蜷医∽サ悶〒蝓九∪繧句庄閭ス諤ァ縺後≠繧九ョ縺ァ縲∽ク譌ヲ謐ョ縺育スョ縺 + continue + + if type(nearest_deform) is Bdef1: + logger.debug( + f"remaining1 nearest_vv: {nearest_vv.vidxs()}, weight_names: [{model.bone_indexes[nearest_deform.index0]}], total_weights: [1]" + ) + + for rv in vv.real_vertices: + weighted_vidxs.append(rv.index) + rv.deform = Bdef1(nearest_deform.index0) + vv.deform = Bdef1(nearest_deform.index0) + + del remaining_vertices[vkey] + elif type(nearest_deform) is Bdef2: + vv.deform = nearest_deform.copy() + # weight_bone1 = model.bones[model.bone_indexes[nearest_deform.index0]] + # weight_bone2 = model.bones[model.bone_indexes[nearest_deform.index1]] + + # bone1_distance = vv.position().distanceToPoint(weight_bone1.position) + # bone2_distance = vv.position().distanceToPoint(weight_bone2.position) if nearest_deform.weight0 < 1 else 0 + # weight_names = np.array([weight_bone1.name, weight_bone2.name]) + # if bone1_distance + bone2_distance != 0: + # total_weights = np.array( + # [ + # bone1_distance / (bone1_distance + bone2_distance), + # bone2_distance / (bone1_distance + bone2_distance), + # ] + # ) + # else: + # total_weights = np.array([1, 0]) + # logger.warning("谿九え繧ァ繧、繝郁ィ育ョ励〒諢丞峙縺帙〓蛟、縺悟・縺」縺溘◆繧√。DEF1繧定ィュ螳壹@縺セ縺吶: 蟇セ雎。鬆らせ[%s]", vv.vidxs()) + # weights = total_weights / total_weights.sum(axis=0, keepdims=1) + # weight_idxs = np.argsort(weights) + + # logger.debug( + # f"remaining2 nearest_vv: {vv.vidxs()}, weight_names: [{weight_names}], total_weights: [{total_weights}]" + # ) + + # if np.count_nonzero(weights) == 1: + # vv.deform = Bdef1(model.bones[weight_names[weight_idxs[-1]]].index) + # elif np.count_nonzero(weights) == 2: + # vv.deform = Bdef2( + # model.bones[weight_names[weight_idxs[-1]]].index, + # model.bones[weight_names[weight_idxs[-2]]].index, + # weights[weight_idxs[-1]], + # ) + # else: + # vv.deform = Bdef4( + # model.bones[weight_names[weight_idxs[-1]]].index, + # model.bones[weight_names[weight_idxs[-2]]].index, + # model.bones[weight_names[weight_idxs[-3]]].index, + # model.bones[weight_names[weight_idxs[-4]]].index, + # weights[weight_idxs[-1]], + # weights[weight_idxs[-2]], + # weights[weight_idxs[-3]], + # weights[weight_idxs[-4]], + # ) + + for rv in vv.real_vertices: + weighted_vidxs.append(rv.index) + rv.deform = vv.deform + + del remaining_vertices[vkey] + + return weighted_vidxs + + +def create_weight( + model: PmxModel, + virtual_vertices: dict, + vertex_map: np.ndarray, + registered_bones: dict, + bone_vertical_distances: dict, + root_yidx: int, + remaining_vertices: dict, +): + + for v_xidx in range(vertex_map.shape[1]): + for v_yidx in range(vertex_map.shape[0]): + if np.isnan(vertex_map[v_yidx, v_xidx]).any(): + continue + + vkey = tuple(vertex_map[v_yidx, v_xidx]) + vv = virtual_vertices[vkey] + + if v_yidx < root_yidx: + # 譬ケ蜈繧医j荳翫ョ蝣エ蜷医√◎縺ョ縺セ縺セ譬ケ蜈繧ヲ繧ァ繧、繝 + vv.deform = Bdef1(registered_bones[root_yidx].index) + + for rv in vv.real_vertices: + rv.deform = vv.deform + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vkey in remaining_vertices: + del remaining_vertices[vkey] + + elif registered_bones[v_yidx]: + # 鬆らせ菴咲スョ縺ォ繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧句エ蜷医。DEF1逋サ骭イ蟇セ雎。 + vv.deform = Bdef1(registered_bones[v_yidx].index) + + for rv in vv.real_vertices: + rv.deform = vv.deform + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vkey in remaining_vertices: + del remaining_vertices[vkey] + else: + above_yidx = root_yidx + if v_yidx > root_yidx: + above_yidx = np.max(np.where(registered_bones[:v_yidx])[0]) + if len(np.where(registered_bones[v_yidx + 1 :])[0]): + below_yidx = v_yidx + 1 + np.min(np.where(registered_bones[v_yidx + 1 :])[0]) + else: + below_yidx = np.max(np.where(registered_bones)[0]) + + if above_yidx == below_yidx: + # 譛ォ遶ッ縺ッBDEF1縺ァ繧ヲ繧ァ繧、繝医r蝪励▲縺ヲ縺翫¥ + vv.deform = Bdef1(registered_bones[below_yidx].index) + + for rv in vv.real_vertices: + rv.deform = vv.deform + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vkey in remaining_vertices: + del remaining_vertices[vkey] + + continue + + # 逋サ骭イ螟悶ョ縺ッBDEF2 + above_weight = np.nan_to_num( + ( + np.sum(bone_vertical_distances[v_yidx:below_yidx, v_xidx]) + / np.sum(bone_vertical_distances[above_yidx:below_yidx, v_xidx]) + ) + ) + + below_weight = np.nan_to_num( + ( + np.sum(bone_vertical_distances[above_yidx:v_yidx, v_xidx]) + / np.sum(bone_vertical_distances[above_yidx:below_yidx, v_xidx]) + ) + ) + + # 縺サ縺シ0縺ョ繧ゅョ縺ッ0縺ォ鄂ョ謠幢シ亥蜻ィ逕ィシ + total_weights = np.array([above_weight, below_weight]) + total_weights[np.isclose(total_weights, 0, equal_nan=True)] = 0 + + if np.count_nonzero(total_weights): + deform_weights = total_weights / total_weights.sum(axis=0, keepdims=1) + + vv.deform = Bdef2( + registered_bones[above_yidx].index, + registered_bones[below_yidx].index, + deform_weights[0], + ) + + for rv in vv.real_vertices: + rv.deform = vv.deform + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vkey in remaining_vertices: + del remaining_vertices[vkey] + else: + pass + + return remaining_vertices + + +def create_bone( + model: PmxModel, + param_option: dict, + material_name: str, + virtual_vertices: dict, + vertex_map: dict, + threshold: float, + max_pos: MVector3D, +): + logger.info("縲%s:%s縲代懊シ繝ウ逕滓", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) + + # 荳ュ蠢繝懊シ繝ウ逕滓 + + # 逡・遘ー + abb_name = param_option["abb_name"] + # 隕ェ繝懊シ繝ウ + parent_bone = model.bones[param_option["parent_bone_name"]] + + # 荳ュ蠢繝懊シ繝ウ + display_name, root_bone = create_root_bone(model, param_option, material_name, max_pos.copy()) + + logger.info("縲%s縲鷹らせ霍晞屬縺ョ邂怜コ", material_name) + + bone_horizonal_distances = np.zeros((vertex_map.shape[0], vertex_map.shape[1])) + bone_vertical_distances = np.zeros((vertex_map.shape[0], vertex_map.shape[1])) + bone_connected = np.zeros((vertex_map.shape[0], vertex_map.shape[1]), dtype=np.int) + + # 蜷鬆らせ縺ョ霍晞屬シ亥蜻ィ縺」縺ス縺蜿ッ閭ス諤ァ縺後≠繧九◆繧√鬆らせ荳蛟九★縺、縺ァ貂ャ繧具シ + for v_yidx in range(vertex_map.shape[0]): + v_xidx = -1 + for v_xidx in range(0, vertex_map.shape[1] - 1): + if not np.isnan(vertex_map[v_yidx, v_xidx]).any() and not np.isnan(vertex_map[v_yidx, v_xidx + 1]).any(): + now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() + next_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx + 1])].position() + bone_horizonal_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(next_v_vec) + + if tuple(vertex_map[v_yidx, v_xidx]) in virtual_vertices[ + tuple(vertex_map[v_yidx, v_xidx + 1]) + ].connected_vvs or tuple(vertex_map[v_yidx, v_xidx]) == tuple(vertex_map[v_yidx, v_xidx + 1]): + # 蜑阪ョ莉ョ諠ウ鬆らせ縺ィ蜷後§縺狗ケ九′縺」縺ヲ縺繧句エ蜷医ゝrue + bone_connected[v_yidx, v_xidx] = True + + if ( + v_yidx < vertex_map.shape[0] - 1 + and not np.isnan(vertex_map[v_yidx, v_xidx]).any() + and not np.isnan(vertex_map[v_yidx + 1, v_xidx]).any() + ): + now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() + next_v_vec = virtual_vertices[tuple(vertex_map[v_yidx + 1, v_xidx])].position() + bone_vertical_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(next_v_vec) + + v_xidx += 1 + if ( + not np.isnan(vertex_map[v_yidx, v_xidx]).any() + and not np.isnan(vertex_map[v_yidx, 0]).any() + and vertex_map.shape[1] > 2 + ): + # 霈ェ繧呈緒縺縺溘ョ繧ょ・繧後→縺(繧ヲ繧ァ繧、繝亥ッセ雎。蜿門セ励ョ譎ゅ↓遽蝗イ謖螳壼・繧九°繧峨%縺薙〒縺ッ蠑キ蛻カ) + if tuple(vertex_map[v_yidx, 0]) in virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].connected_vvs: + # 讓ェ縺ョ莉ョ諠ウ鬆らせ縺ィ郢九′縺」縺ヲ縺繧句エ蜷医ゝrue縺ァ譛牙柑縺ェ霍晞屬繧貞・繧後※縺翫¥ + bone_connected[v_yidx, v_xidx] = True + + now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() + next_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, 0])].position() + bone_horizonal_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(next_v_vec) + else: + # 縺ィ繧翫≠縺医★INT譛螟ァ蛟、繧貞・繧後※縺翫¥ + bone_horizonal_distances[v_yidx, v_xidx] = np.iinfo(np.int).max + + logger.debug("bone_horizonal_distances ------------") + logger.debug(bone_horizonal_distances.tolist()) + logger.debug("bone_vertical_distances ------------") + logger.debug(bone_vertical_distances.tolist()) + logger.debug("bone_connected ------------") + logger.debug(bone_connected.tolist()) + + # 繝懊シ繝ウ逋サ骭イ譛臥┌ + regist_bones = np.zeros(vertex_map.shape[0], dtype=np.int) + + root_yidx = np.where( + np.array([not np.isnan(vertex_map[yidx, :]).any() for yidx in range(vertex_map.shape[0])]) == True + )[0][0] + + # 髢馴囈縺碁らせ繧ソ繧、繝励ョ蝣エ蜷医∬ヲ丞援逧縺ォ髢薙r遨コ縺代k + for v_yidx in list(range(root_yidx, vertex_map.shape[0], param_option["vertical_bone_density"])) + [ + vertex_map.shape[0] - 1, + ]: + regist_bones[v_yidx] = True + + registered_bones = np.full(vertex_map.shape[0], fill_value=None) + prev_bone = None + for v_yidx in range(vertex_map.shape[0]): + if not regist_bones[v_yidx]: + # 逋サ骭イ蟇セ雎。縺ァ縺ッ縺ェ縺蝣エ蜷医√せ繝ォ繝シ + continue + + # 隕ェ縺ッ譌「縺ォ繝「繝繝ォ縺ォ逋サ骭イ貂医∩縺ョ繧ゅョ繧帝∈縺カ + parent_bone = root_bone if v_yidx == root_yidx else prev_bone + + bone_name = f"{abb_name}-{(v_yidx + 1):03d}" + + bone_pos = MVector3D( + np.mean(vertex_map[v_yidx, np.unique(np.where(np.isnan(vertex_map[v_yidx, :]) == False)[0])], axis=0) + * threshold + ) + bone = Bone(bone_name, bone_name, bone_pos, parent_bone.index, 0, 0x0000 | 0x0002 | 0x0800) + + bone.parent_index = parent_bone.index + bone.local_x_vector = (bone.position - parent_bone.position).normalized() + bone.local_z_vector = MVector3D.crossProduct(bone.local_x_vector, MVector3D(1, 0, 0)) + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医ョ縺ソ繝懊シ繝ウ菫晄戟 + bone.index = len(model.bones) + parent_bone.tail_index = bone.index + if v_yidx < vertex_map.shape[0] - 1: + bone.flag |= 0x0008 | 0x0010 | 0x0001 + registered_bones[v_yidx] = bone + + model.display_slots[display_name].references.append((0, bone.index)) + + logger.debug(f"tmp_all_bones: {bone.name}, pos: {bone.position.to_log()}") + + model.bones[bone_name] = bone + model.bone_indexes[bone.index] = bone_name + + prev_bone = bone + + return ( + root_bone, + virtual_vertices, + registered_bones, + bone_vertical_distances, + bone_horizonal_distances, + bone_connected, + root_yidx, + ) + + +def get_bone_name(self, abb_name: str, v_yno: int, v_xno: int): + return f"{abb_name}-{(v_yno):03d}-{(v_xno):03d}" + + +def create_root_bone(model: PmxModel, param_option: dict, material_name: str, root_pos: MVector3D): + # 逡・遘ー + abb_name = param_option["abb_name"] + # 陦ィ遉コ譫蜷 + display_name = f"{abb_name}:{material_name}" + # 隕ェ繝懊シ繝ウ + parent_bone = model.bones[param_option["parent_bone_name"]] + + # 荳ュ蠢繝懊シ繝ウ + root_bone = Bone( + f"{abb_name}荳ュ蠢", + f"{abb_name}Root", + root_pos, + parent_bone.index, + 0, + 0x0000 | 0x0002 | 0x0004 | 0x0008 | 0x0010, + ) + + root_bone.index = len(model.bones) + model.bones[root_bone.name] = root_bone + model.bone_indexes[root_bone.index] = root_bone.name + + # 陦ィ遉コ譫 + model.display_slots[display_name] = DisplaySlot(display_name, display_name, 0, 0) + model.display_slots[display_name].references.append((0, model.bones[root_bone.name].index)) + + return display_name, root_bone + + +def create_ring(virtual_vertices: dict, vkey: tuple, rings: list): + rings.append(vkey) + + vv: VirtualVertex = virtual_vertices[vkey] + connected_vecs = {} + for connected_vkey in vv.connected_vvs: + if connected_vkey not in rings and connected_vkey in virtual_vertices: + connected_vec = (vv.position() - virtual_vertices[connected_vkey].position()).normalized() + connected_vecs[connected_vkey] = connected_vec.data() + next_vkey = list(connected_vecs.keys())[np.argmin(np.abs(list(connected_vecs.values())), axis=0)[1]] + if np.min(np.abs(list(connected_vecs.values())), axis=0)[1] > 0.3: + return rings + + return create_ring(virtual_vertices, next_vkey, rings) + + +def create_vertex_map( + model: PmxModel, + param_option: dict, + material_name: str, + target_vertices: list, +): + logger.info("縲%s:%s縲鷹らせ繝槭ャ繝礼函謌", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) + + # 谿矩らせ繝ェ繧ケ繝 + remaining_vertices = {} + + parent_bone = model.bones[param_option["parent_bone_name"]] + + # 荳譌ヲ蜈ィ菴薙ョ菴咲スョ繧呈滑謠。 + n = 0 + vertex_positions = {} + for index_idx in model.material_indices[material_name]: + for v0_idx, v1_idx in zip( + model.indices[index_idx], + model.indices[index_idx][1:] + [model.indices[index_idx][0]], + ): + if v0_idx not in target_vertices or v1_idx not in target_vertices: + continue + vertex_positions[v0_idx] = model.vertex_dict[v0_idx].position.data() + + n += 1 + if n > 0 and n % 1000 == 0: + logger.info("-- 蜈ィ菴薙Γ繝繧キ繝・遒コ隱: %s蛟狗岼:邨ゆコ", n) + + material_mean_pos = MVector3D(np.mean(list(vertex_positions.values()), axis=0)) + logger.info("%s: 譚占ウェ鬆らせ縺ョ荳ュ蠢轤ケ邂怜コ: %s", material_name, material_mean_pos.to_log()) + + # 蜷鬆らせ縺ョ菴咲スョ縺ィ縺ョ蟾ョ蛻縺九i霍晞屬繧呈クャ繧 + v_distances = np.linalg.norm( + (np.array(list(vertex_positions.values())) - parent_bone.position.data()), ord=2, axis=1 + ) + # 隕ェ繝懊シ繝ウ縺ォ譛繧りソ代>鬆らせ + nearest_vertex_idx = list(vertex_positions.keys())[np.argmin(v_distances)] + # 隕ェ繝懊シ繝ウ縺ォ譛繧る□縺鬆らせ + farest_vertex_idx = list(vertex_positions.keys())[np.argmax(v_distances)] + # 譚占ウェ蜈ィ菴薙ョ蛯セ縺 + material_direction = ( + (model.vertex_dict[farest_vertex_idx].position - model.vertex_dict[nearest_vertex_idx].position) + .abs() + .normalized() + .data()[np.where(np.abs([0, 1, 0]))] + )[0] + logger.info("%s: 譚占ウェ鬆らせ縺ョ蛯セ縺咲ョ怜コ: %s", material_name, round(material_direction, 5)) + + # 鬆らせ髢薙ョ霍晞屬 + # https://blog.shikoan.com/distance-without-for-loop/ + all_vertex_diffs = np.expand_dims(np.array(list(vertex_positions.values())), axis=1) - np.expand_dims( + np.array(list(vertex_positions.values())), axis=0 + ) + all_vertex_distances = np.sqrt(np.sum(all_vertex_diffs**2, axis=-1)) + # 鬆らせ蜷悟」ォ縺ョ霍晞屬縺九i髢セ蛟、逕滓 + threshold = np.min(all_vertex_distances[all_vertex_distances > 0]) * 0.8 + + logger.info("%s: 譚占ウェ鬆らせ縺ョ髢セ蛟、邂怜コ: %s", material_name, round(threshold, 5)) + + logger.info("%s: 莉ョ諠ウ鬆らせ繝ェ繧ケ繝医ョ逕滓", material_name) + + virtual_vertices = {} + all_poses = {} + n = 0 + for index_idx in model.material_indices[material_name]: + # 鬆らせ縺ョ邨縺ソ蜷医o縺帙°繧蛾擇INDEX繧貞シ輔¥ + if ( + model.indices[index_idx][0] not in target_vertices + or model.indices[index_idx][1] not in target_vertices + or model.indices[index_idx][2] not in target_vertices + ): + # 3縺、謠縺」縺ヲ縺ェ縺蝣エ蜷医√せ繝ォ繝シ + continue + + v0_idx = model.indices[index_idx][0] + v1_idx = model.indices[index_idx][1] + v2_idx = model.indices[index_idx][2] + + v0 = model.vertex_dict[v0_idx] + v1 = model.vertex_dict[v1_idx] + v2 = model.vertex_dict[v2_idx] + + v0_key = v0.position.to_key(threshold) + v1_key = v1.position.to_key(threshold) + v2_key = v2.position.to_key(threshold) + + for vv0_key, vv1_key, vv2_key, vv0 in [ + (v0_key, v1_key, v2_key, v0), + (v1_key, v2_key, v0_key, v1), + (v2_key, v0_key, v1_key, v2), + ]: + # 莉ョ諠ウ鬆らせ逋サ骭イシ郁ゥイ蠖馴らせ蟇セ雎。シ + if vv0_key not in virtual_vertices: + virtual_vertices[vv0_key] = VirtualVertex(vv0_key) + all_poses[vv0_key] = vv0.position.data() + virtual_vertices[vv0_key].append([vv0], [vv1_key, vv2_key], [index_idx]) + + # 谿矩らせ繝ェ繧ケ繝医↓縺セ縺壹ッ逋サ骭イ + if vv0_key not in remaining_vertices: + remaining_vertices[vv0_key] = virtual_vertices[vv0_key] + + logger.debug( + f"笘陦ィ index[{index_idx}], v0[{v0.index}:{v0_key}], v1[{v1.index}:{v1_key}], v2[{v2.index}:{v2_key}], pa[{parent_bone.position.to_log()}]" + ) + + n += 1 + + if n > 0 and n % 500 == 0: + logger.info("-- 繝。繝繧キ繝・遒コ隱: %s蛟狗岼:邨ゆコ", n) + + max_pos = np.max(list(all_poses.values()), axis=0) + max_key = MVector3D(max_pos).to_key(threshold) + + min_pos = np.min(list(all_poses.values()), axis=0) + min_key = MVector3D(min_pos).to_key(threshold) + + median_pos = np.median(list(all_poses.values()), axis=0) + median_key = MVector3D(median_pos).to_key(threshold) + + median_vkey = min_vkey = max_vkey = None + for x, y, z in all_poses.keys(): + if y == median_key[1] and not median_vkey: + median_vkey = (x, y, z) + if y == min_key[1] and not min_vkey: + min_vkey = (x, y, z) + if y == max_key[1] and not max_vkey: + max_vkey = (x, y, z) + + min_pos = virtual_vertices[min_vkey].position() + max_pos = virtual_vertices[max_vkey].position() + + # 繝ェ繝ウ繧ー蜿門セ + median_rings = create_ring(virtual_vertices, median_vkey, []) + + all_upper_vkeys = [] + all_lower_vkeys = [] + for mi, target_vkey in enumerate(median_rings): + # 譬ケ蜈縺ォ蜷代¢縺ヲ縺ョ繝ゥ繧、繝ウ + upper_vkeys, upper_vscores = create_vertex_line_map( + target_vkey, + max_pos, + target_vkey, + virtual_vertices, + [target_vkey], + [], + [], + ) + + # 鬮ェ荳企Κ縺ョ騾イ陦梧婿蜷代↓蜷医o縺帙※荳九r讀懷コ縺吶k + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + top_x_pos = ( + virtual_vertices[upper_vkeys[-2]].position() - virtual_vertices[upper_vkeys[-1]].position() + ).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(y) + top_y_pos = MVector3D(1, 0, 0) + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(z) + top_z_pos = MVector3D.crossProduct(top_x_pos, top_y_pos) + top_qq = MQuaternion.fromDirection(top_z_pos, top_y_pos) + + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(virtual_vertices[target_vkey].position()) + mat.rotate(top_qq) + + below_pos = mat * MVector3D(-3, 0, 0) + + lower_vkeys, lower_vscores = create_vertex_line_map( + target_vkey, + below_pos, + target_vkey, + virtual_vertices, + [target_vkey], + [], + [], + ) + + all_upper_vkeys.append(upper_vkeys) + all_lower_vkeys.append(lower_vkeys) + + # XY縺ョ譛螟ァ縺ィ譛蟆上ョ謚ス蜃コ + xu = len(all_upper_vkeys) + upper_y = np.max([len(vk) for i, vk in enumerate(all_upper_vkeys)]) + lower_y = np.max([len(vk) for i, vk in enumerate(all_lower_vkeys)]) + + # 蟄伜惠縺励↑縺鬆らせINDEX縺ァ莠梧ャ。蜈驟榊怜晄悄蛹 + vertex_map = np.full((upper_y + lower_y, xu, 3), (np.nan, np.nan, np.nan)) + + # 譬ケ蜈縺九i鬆縺ォ繝槭ャ繝励↓蝓九a縺ヲ縺縺 + for x, vkeys in enumerate(all_upper_vkeys): + for y, vkey in enumerate(reversed(vkeys)): + vv = virtual_vertices[vkey] + if not vv.vidxs(): + continue + + logger.debug(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") + + vertex_map[upper_y - y, x] = vkey + + for x, vkeys in enumerate(all_lower_vkeys): + for y, vkey in enumerate(reversed(vkeys)): + vv = virtual_vertices[vkey] + if not vv.vidxs(): + continue + + logger.debug(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") + + vertex_map[upper_y + y, x] = vkey + + return vertex_map, virtual_vertices, threshold, max_pos, remaining_vertices + + +def create_vertex_line_map( + bottom_key: tuple, + top_pos: MVector3D, + from_key: tuple, + virtual_vertices: dict, + vkeys: list, + vscores: list, + registed_vkeys: list, + loop=0, +): + + if loop > 500: + return None, None + + from_vv = virtual_vertices[from_key] + from_pos = from_vv.position() + + bottom_vv = virtual_vertices[bottom_key] + bottom_pos = bottom_vv.position() + + local_next_base_pos = MVector3D(1, 0, 0) + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + top_x_pos = (top_pos - bottom_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(y) + top_y_pos = MVector3D(1, 0, 0) + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(z) + top_z_pos = MVector3D.crossProduct(top_x_pos, top_y_pos) + top_qq = MQuaternion.fromDirection(top_z_pos, top_y_pos) + logger.debug( + f" - top({bottom_vv.vidxs()}): x[{top_x_pos.to_log()}], y[{top_y_pos.to_log()}], z[{top_z_pos.to_log()}]" + ) + + scores = [] + prev_dots = [] + for n, to_key in enumerate(from_vv.connected_vvs): + if to_key not in virtual_vertices: + scores.append(0) + prev_dots.append(0) + logger.debug(f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_key}], 蟇セ雎。螟") + continue + + if to_key in registed_vkeys: + scores.append(0) + prev_dots.append(0) + logger.debug(f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_key}], 逋サ骭イ貂医∩") + continue + + to_vv = virtual_vertices[to_key] + to_pos = to_vv.position() + + direction_dot = MVector3D.dotProduct(top_x_pos, (to_pos - from_pos).normalized()) + + if to_key in vkeys: + # 蛻ー驕疲ク医∩縺ョ繝吶け繝医Ν縺ォ縺ッ陦後°縺帙↑縺 + scores.append(0) + prev_dots.append(0) + logger.debug( + f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蛻ー驕疲ク医∩" + ) + continue + + if direction_dot < 0.3: + # 蜿榊ッセ譁ケ蜷代ョ繝吶け繝医Ν縺ォ縺ッ陦後°縺帙↑縺 + scores.append(0) + prev_dots.append(0) + logger.debug( + f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蜿榊ッセ譁ケ蜷" + ) + continue + + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(from_pos) + mat.rotate(top_qq) + + local_next_vpos = (mat.inverted() * to_pos).normalized() + + vec_yaw1 = (local_next_base_pos * MVector3D(1, 0, 1)).normalized() + vec_yaw2 = (local_next_vpos * MVector3D(1, 0, 1)).normalized() + yaw_score = calc_ratio(MVector3D.dotProduct(vec_yaw1, vec_yaw2), -1, 1, 0, 1) + + vec_pitch1 = (local_next_base_pos * MVector3D(0, 1, 1)).normalized() + vec_pitch2 = (local_next_vpos * MVector3D(0, 1, 1)).normalized() + pitch_score = calc_ratio(MVector3D.dotProduct(vec_pitch1, vec_pitch2), -1, 1, 0, 1) + + vec_roll1 = (local_next_base_pos * MVector3D(1, 1, 0)).normalized() + vec_roll2 = (local_next_vpos * MVector3D(1, 1, 0)).normalized() + roll_score = calc_ratio(MVector3D.dotProduct(vec_roll1, vec_roll2), -1, 1, 0, 1) + + # 蜑埼らせ縺ィ縺ョ蜀遨榊キョ繧定諷ョ縺吶k蝣エ蜷 + prev_dot = ( + MVector3D.dotProduct( + (virtual_vertices[vkeys[0]].position() - virtual_vertices[vkeys[1]].position()).normalized(), + (to_pos - virtual_vertices[vkeys[0]].position()).normalized(), + ) + if len(vkeys) > 1 + else 1 + ) + + if prev_dot < 0.5: + # 繧コ繝ャ縺滓婿蜷代↓縺ッ陦後°縺帙↑縺 + scores.append(0) + prev_dots.append(0) + logger.debug( + f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}, 蜑阪ぜ繝ャ譁ケ蜷" + ) + continue + + score = ((yaw_score * 20) + pitch_score + (roll_score * 2)) * (prev_dot**3) + + # scores.append(score * (2 if to_key in top_keys else 1)) + scores.append(score) + prev_dots.append(prev_dot * direction_dot) + + logger.debug( + f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], prev_dot[{prev_dot}], local_next_vpos[{local_next_vpos.to_log()}], score: [{score}], yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}" + ) + + if np.count_nonzero(scores) == 0: + # 繧ケ繧ウ繧「縺御サ倥¢繧峨l縺ェ縺上↑縺」縺溘i邨ゆコ + return vkeys, vscores + + # 譛繧ゅせ繧ウ繧「縺ョ鬮倥>INDEX繧呈治逕ィ + nearest_idx = np.argmax(scores) + vertical_key = from_vv.connected_vvs[nearest_idx] + + # 蜑阪ョ霎コ縺ィ縺ョ蜀遨榊キョ繧定諷ョ縺吶k + prev_diff_dot = ( + MVector3D.dotProduct( + (virtual_vertices[vkeys[0]].position() - virtual_vertices[vkeys[1]].position()).normalized(), + (virtual_vertices[vertical_key].position() - virtual_vertices[vkeys[0]].position()).normalized(), + ) + if len(vkeys) > 1 + else 1 + ) + + logger.debug( + f"direction: from: [{virtual_vertices[from_key].vidxs()}], to: [{virtual_vertices[vertical_key].vidxs()}], prev_diff_dot[{round(prev_diff_dot, 4)}]" + ) + + vkeys.insert(0, vertical_key) + vscores.insert(0, np.max(scores) * prev_diff_dot) + + # 鬮ェ荳企Κ縺ョ騾イ陦梧婿蜷代↓蜷医o縺帙※騾イ陦梧婿蜷代r讀懷コ縺吶k + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + top_x_pos = (virtual_vertices[vertical_key].position() - virtual_vertices[from_key].position()).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(y) + top_y_pos = MVector3D(1, 0, 0) + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(z) + top_z_pos = MVector3D.crossProduct(top_x_pos, top_y_pos) + top_qq = MQuaternion.fromDirection(top_z_pos, top_y_pos) + + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(virtual_vertices[from_key].position()) + mat.rotate(top_qq) + + top_pos = mat * MVector3D(3, 0, 0) + + return create_vertex_line_map( + bottom_key, + top_pos, + vertical_key, + virtual_vertices, + vkeys, + vscores, + registed_vkeys, + loop + 1, + ) + + +def get_edge_lines(edge_line_pairs: dict, start_vkey: tuple, edge_lines: list, edge_vkeys: list, loop=0): + if len(edge_vkeys) >= len(edge_line_pairs.keys()) or loop > 500: + return start_vkey, edge_lines, edge_vkeys + + if not start_vkey: + # 荳: Y(髯埼) - X(荳ュ螟ョ謠縺) - Z(髯埼) + sorted_edge_line_pairs = sorted( + list(set(edge_line_pairs.keys()) - set(edge_vkeys)), key=lambda x: (-x[1], abs(x[0]), -x[2]) + ) + start_vkey = sorted_edge_line_pairs[0] + edge_lines.append([start_vkey]) + edge_vkeys.append(start_vkey) + + # 荳: X(荳ュ螟ョ謠縺) - Z(髯埼) - Y(髯埼) + sorted_edge_line_pairs = sorted(edge_line_pairs[start_vkey], key=lambda x: (abs(x[0]), -x[2], -x[1])) + + for next_vkey in sorted_edge_line_pairs: + if next_vkey not in edge_vkeys: + edge_lines[-1].append(next_vkey) + edge_vkeys.append(next_vkey) + start_vkey, edge_lines, edge_vkeys = get_edge_lines( + edge_line_pairs, next_vkey, edge_lines, edge_vkeys, loop + 1 + ) + + return None, edge_lines, edge_vkeys + + +if __name__ == "__main__": + exec_joint() diff --git a/pmx_tailor.spec b/pmx_tailor.spec index 6ed369a..4bbfce2 100644 --- a/pmx_tailor.spec +++ b/pmx_tailor.spec @@ -26,7 +26,7 @@ exe = EXE(pyz, a.zipfiles, a.datas, [], - name='PmxTailor_2.00.03', + name='PmxTailor_2.01.00', debug=False, bootloader_ignore_signals=False, strip=False, diff --git a/pyinstaller64.bat b/pyinstaller64.bat index 3f97b0d..3143ca7 100644 --- a/pyinstaller64.bat +++ b/pyinstaller64.bat @@ -8,6 +8,12 @@ cd /d %~dp0 cls +del dist\*.lnk +move /y dist\*.exe dist\past + activate vmdsizing_np && cd src && python translate.py && cd .. && activate vmdsizing_cython && src\setup_install.bat && pyinstaller --clean pmx_tailor.spec && copy /y archive\Readme.txt dist\Readme.txt && copy /y archive\β版Readme.txt dist\β版Readme.txt && activate vmdsizing_np && cd src && python lnk.py && cd .. rem activate vmdsizing_cython && pyinstaller --clean pmx_tailor.spec +net start beep +rundll32 user32.dll,MessageBeep +net stop beep diff --git a/rivision.txt b/rivision.txt index 562e023..a8ce6bc 100644 --- a/rivision.txt +++ b/rivision.txt @@ -696,6 +696,116 @@ PmxTailor_2.00.03_ ・一枚物メッシュの根元頂点CSV必須チェックを除外 ・縦ジョイント生成に失敗した場合の対処方法追加 +https://fire.st/Hs8nKd8 +PmxTailor_2.00.04_β01 (2022/11/30) +・下部エッジを検出する際の閾値が全体の中央値になっていたので、上部エッジの中央値に修正 + (スリットはエッジ区分を分けなくても、角に沿って適宜ボーンが配置されるようになっていたため) +・縦ジョイントがなかった場合のログを、根元とそれ以降でメッセージを分けるよう修正 + (裾がギザギザで縦ジョイントが作れなかった場合には縦ジョイントがなくても問題がないため、 +  警告の仕方を弱めに変更) + +https://fire.st/cq73yZK +PmxTailor_2.00.04_β02 (2023/01/21) miumiu +・髪のジョイントY値を0に変更(捩れないように) +・モデルコメントに指定したパラの出力を追加 +・根元推定:縮尺の処理を理想上の縮尺に合わせた根元を推定するよう変更 + ・デフォルトは角度なので、ほぼ影響はなし +・スリットのボーン生成に失敗する場合があったのを修正 + ・ボーン密度を大きく(荒く)したときに隙間にハマるボーンが生成されなかった + ・切れ目の根元のボーンが片方生成されない場合があったのを修正 +・メッシュの上下を分けるロジックを修正 + ・親ボーンに下半身(親ボーンがメッシュより上)を想定していて、襟など首回りのメッシュで上半身2を親とした場合などに対応できてなかったのを修正 +・剛体の向きがおかしくなる場合があるのを修正 + ・剛体のY軸方向の判定がミスってた + +https://fire.st/zTHbttP +PmxTailor_2.00.04_β03 (2023/02/05) miumiu +・一頂点だけで繋がっているメッシュを切り分けるよう修正 +・特殊形状「面抜け」追加 + ・抜けがある場合、仮想エッジを張るよう処理追加 +・エッジの検出ルートを変更 + ・一辺(2つの頂点)が見つかってる場合、それと辺が内積が大きいものを選択する +  既存は「X(中央揃え) - Z(降順) - Y(降順)」でソートしたもので大きいものを選択していた +・線分の交差判定を修正 +・割りに応じたボーンの張り方を修正 + ・仮想頂点がある場合、そこは面がある前提でボーンを張る + ・縦軸の末端以降は末端仮想頂点を1つだけ作成して、その後はボーンを張らない + ・メッシュが不定形の場合、それを加味して縦横を張る +・スリットや水平メッシュのウェイト・ボーン・剛体・ジョイントを修正 + +https://fire.st/QFLpQrc +PmxTailor_2.01.00_β01 (2023/02/05) miumiu +・ジョイントの位置のデフォルト設定をボーン位置に変更 + ・その方が荒いメッシュで安定しやすい +・面抜け→面欠けにパラメーター名変更 +・複数マップの際にボーンの張り方フラグをひとつ前の頂点マップを参照して決めるよう修正 +・スライダーによるジョイント制限値の算出式を変更 + ・ボーン位置の場合、ボーン間より少し柔らかい設定 + ・ジョイントの制限値は「柔らかさ」パラ + ・ジョイントのばねは「張り」パラ +・プリミティブ設定パラを調整 + +https://fire.st/gtD6KTe +PmxTailor_2.01.00_β02 (2023/02/05) miumiu +・仮登録用ジョイントキーの生成にボーンマップのINDEXが入って無くて上書きされてたのを修正 +・バネの計算数式を修正 + +https://fire.st/4bPaUVH +PmxTailor_2.01.00_β03 (2023/02/05) miumiu +・Vroid2Pmxインポート物理のパラ調整 + +https://fire.st/z3kOMt7 +PmxTailor_2.01.00_β04 (2023/02/11) miumiu +・物理のパラ調整 +・ウェイト塗りの順番を修正 + ・マップ頂点→残頂点→グラデ頂点→裏頂点 となっており、二重に不要なウェイトが塗られる場合があった + ・マップ頂点→グラデ頂点→裏頂点→残頂点で塗れるよう修正 +・スリットメッシュで張るボーンのマッピングを修正 +・親ボーンが見つからなかった場合に警告してルートボーンに紐付けて続けるよう修正 + ・大体の場合、不要な非表示ボーン +・ジョイントの順番をボーン・剛体の順番(縦方向)に揃えた +・斜めジョイントのY方向に若干の移動を許可 + +https://fire.st/I85BYZy +PmxTailor_2.01.00_β05 (2023/02/11) miumiu +・自身と同じ位置のボーンを親に持つ子ボーンの判定条件を厳しめに変更 + +https://fire.st/K5P8NjC +PmxTailor_2.01.00_β06 (2023/02/12) miumiu +・残ウェイトに渡す頂点INDEXリストの保持方法を修正 +・末端ボーンの登録FLGがONにならない場合を修正(ボーン密度からの計算が一部ミスってた) +・同一最上部キーで分けた時に、スリットの途中の辺が一辺だけ抽出されるのを除外 + ・面欠けの辺が一辺だけのとき正常に抽出できない +・ボーンのマッピングを修正 + ・X軸方向に欠けてる箇所の抽出が間違っていた(縦に不要なボーンが張られていた) +・円周の最後の頂点ウェイトを塗る際に縦方向の距離が測れて無くてウェイトが0になっていたのを修正 +・Y軸方向のボーン付与FLGを全体のマップを通して同じ箇所にボーンを張れるよう判定処理追加 +・一枚布の横末端の剛体を折り返しで作成するよう機能追加 +・親剛体制限をデフォルトFALSEに(制限がキツすぎるので再考) + +https://fire.st/ZVha4UM +PmxTailor_2.01.00_β07 (2023/02/12) miumiu +・胸物理のパラ調整 +・折り返し剛体の大きさや位置などを、ひとつ前の剛体と合わせるよう修正 +・折り返し剛体の生成判定が間違っていたので修正 +・仮想エッジを作った場合、その結果としてエッジではなくなった辺がある場合、除外するよう修正 + ・エッジを辿った際に意図せぬ箇所で走査処理が終了してしまう +・ひとつ先の仮想頂点を取得する際に、自分以降の条件が抜けていたのを修正 +・プリセット「ウール」を追加 +・横優先の並び順に戻した +・ジョイントの横移動制限をボーンの距離に合わせた量にする + +https://fire.st/oIQ0EGA +PmxTailor_2.01.00_β08 (2023/02/13) miumiu +・横優先の並び順が戻し切れてなかったので修正 +・頂点マップが一列だった場合に縦方向の距離が取れておらず、ウェイトが塗れてなかったのを修正 + +https://fire.st/Rf4Vd9s +PmxTailor_2.01.00_β09 (2023/02/13) miumiu +・再利用で一列だけで布プリセットを使用した場合、横を強制的に参照しようとしてエラーになっていたのを修正 + + + VmdSizing_5.01.08_β01, PmxTailor_2.00.03_β02 をβリリースしました! @@ -720,15 +830,31 @@ https://com.nicovideo.jp/community/co5387214 -PmxTailor_2.00.02_β04 をβリリースしました〜 +PmxTailor_2.01.00_β07 をβリリースしました! -・SDEF+再利用オプション時にボーンマップ生成に失敗していたのを修正 -・ジョイント生成時のパラマッピング時INDEX割り当て処理変更 +あちこちお待たせしていてすみません。 +やっとベータ版をお出しできる精度に出来たと思います。 + +・剛体とジョイントの張り方を変更 +・物理パラ見直し +・プリセット「ウール」追加 +・メッシュ走査の方法を変更 +・モデルコメントに指定した全パラの出力を追加 +・スリットの分かれ目のボーン生成ルールを修正 +・特殊形状「面欠け」追加 +・ウェイト塗りの順番を修正 ニコニコミュニティ(自動承認)にてβ版配布中です。 https://com.nicovideo.jp/community/co5387214 +・より安定性の高いボーン位置に + + + +670 + + @@ -747,15 +873,18 @@ PmxTailor ver1.00.02 -https://fire.st/M2dMvMy +https://fire.st/Rf4Vd9s

-・剛体とジョイントの仮想頂点取得時のチェック追加
-・末端の仮想ボーンを常にメッシュ一行分の幅で生成するよう変更
-・頂点マップ検算時、横の繋がりよりも根元を繋げることを優先するよう変更
-・「密度基準:中央」時のボーンの生成箇所を「奇数 = 真ん中、偶数 = 始点寄り」に変更
-・一枚物メッシュの根元頂点CSV必須チェックを除外
-・縦ジョイント生成に失敗した場合の対処方法追加
+・剛体とジョイントの張り方を変更
+・物理パラ見直し
+・プリセット「ウール」追加
+・メッシュ走査の方法を変更
+・モデルコメントに指定した全パラの出力を追加
+・スリットの分かれ目のボーン生成ルールを修正
+・特殊形状「面欠け」追加
+・ウェイト塗りの順番を修正
+・頂点マップが一列だった場合に縦方向の距離が取れておらず、ウェイトが塗れてなかったのを修正


ぜひ使っていただいて、感想・不具合報告等お願いいたします。
diff --git a/src/executor.py b/src/executor.py index 82e3e55..babae54 100644 --- a/src/executor.py +++ b/src/executor.py @@ -12,7 +12,7 @@ from utils.MLogger import MLogger from utils import MFileUtils -VERSION_NAME = "2.00.03" +VERSION_NAME = "2.01.00" # 謖謨ー陦ィ險倥↑縺励∵怏蜉ケ蟆乗焚轤ケ譯∵焚6縲30繧定カ縺医k縺ィ逵∫払縺ゅj縲∽ク陦後ョ譁蟄玲焚200 np.set_printoptions(suppress=True, precision=6, threshold=30, linewidth=200) diff --git a/src/form/panel/ParamPanel.py b/src/form/panel/ParamPanel.py index 8fe38a6..a5b8c98 100644 --- a/src/form/panel/ParamPanel.py +++ b/src/form/panel/ParamPanel.py @@ -190,10 +190,14 @@ def on_vroid2pmx_import(self, event: wx.Event): self.physics_list[-1].set_simple_primitive(event) - if "閠ウ" in vroid2pmx_setting["abb_name"]: + if "鬮ェH" in vroid2pmx_setting["abb_name"]: + self.physics_list[-1].simple_mass_slider.SetValue(1.0) + self.physics_list[-1].simple_air_resistance_slider.SetValue(2.7) + self.physics_list[-1].simple_shape_maintenance_slider.SetValue(3.8) + elif "閠ウ" in vroid2pmx_setting["abb_name"]: + self.physics_list[-1].simple_mass_slider.SetValue(0.8) self.physics_list[-1].simple_air_resistance_slider.SetValue(5) - self.physics_list[-1].simple_shape_maintenance_slider.SetValue(5) - self.physics_list[-1].set_mass(event) + self.physics_list[-1].simple_shape_maintenance_slider.SetValue(3) elif ( "CS" in vroid2pmx_setting["abb_name"] or "SK" in vroid2pmx_setting["abb_name"] @@ -556,6 +560,7 @@ def __init__( choices=[ logger.transtext("蟶(繧ウ繝繝医Φ)"), logger.transtext("蟶(繧キ繝ォ繧ッ)"), + logger.transtext("蟶(繧ヲ繝シ繝ォ)"), logger.transtext("蟶(繝吶Ν繝吶ャ繝)"), logger.transtext("蟶(繝ャ繧カ繝シ)"), logger.transtext("蟶(繝繝九Β)"), @@ -576,7 +581,9 @@ def __init__( ) self.simple_special_shape_txt.SetToolTip( logger.transtext( - "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ" + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n" + + "蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n" + + "髱「谺縺: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√お繝繧ク縺ァ縺ッ縺ェ縺上〒縺薙⊂縺薙@縺ヲ縺繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n" ) ) self.simple_special_shape_txt.Wrap(-1) @@ -585,10 +592,10 @@ def __init__( self.simple_special_shape_ctrl = wx.Choice( self.simple_window, id=wx.ID_ANY, - choices=[logger.transtext("縺ェ縺"), logger.transtext("蜈ィ縺ヲ陦ィ髱「")], + choices=[logger.transtext("縺ェ縺"), logger.transtext("蜈ィ縺ヲ陦ィ髱「"), logger.transtext("髱「谺縺")], ) self.simple_special_shape_ctrl.SetToolTip(self.simple_special_shape_txt.GetToolTipText()) - self.simple_special_shape_ctrl.Bind(wx.EVT_CHOICE, self.main_frame.file_panel_ctrl.on_change_file) + self.simple_special_shape_ctrl.Bind(wx.EVT_CHOICE, self.on_special_shape) self.simple_header_grid_sizer.Add(self.simple_special_shape_ctrl, 0, wx.ALL, 5) self.simple_param_sizer.Add(self.simple_header_grid_sizer, 0, wx.ALL | wx.EXPAND, 0) @@ -712,7 +719,7 @@ def __init__( self.simple_window, wx.ID_ANY, logger.transtext("譟斐i縺九&"), wx.DefaultPosition, wx.DefaultSize, 0 ) self.simple_air_resistance_txt.SetToolTip( - logger.transtext("譚占ウェ縺ョ譟斐i縺九&縲ょ、ァ縺阪¥縺ェ繧九⊇縺ゥ縺吶$縺ォ蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ域ク幄。ー縺碁ォ倥>シ噂n蜑帑ス薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ蠑キ縺慕ュ峨↓蠖ア髻ソ縺励∪縺吶") + logger.transtext("譚占ウェ縺ョ譟斐i縺九&縲ょ央菴薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍募屓霆「蛻カ髯舌↓蠖ア髻ソ縺励∪縺吶\n蟆上&縺上↑繧九⊇縺ゥ繧医¥螟牙ス「縺励√☆縺舌↓蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ亥屓霆「蛻カ髯舌′螟ァ縺阪¥縲∵ク幄。ー縺碁ォ倥>シ") ) self.simple_air_resistance_txt.Wrap(-1) self.simple_grid_sizer.Add(self.simple_air_resistance_txt, 0, wx.ALL, 5) @@ -754,7 +761,9 @@ def __init__( self.simple_shape_maintenance_txt = wx.StaticText( self.simple_window, wx.ID_ANY, logger.transtext("蠑オ繧"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.simple_shape_maintenance_txt.SetToolTip(logger.transtext("譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ蠑キ縺慕ュ峨↓蠖ア髻ソ縺励∪縺吶")) + self.simple_shape_maintenance_txt.SetToolTip( + logger.transtext("譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ繝舌ロ縺ョ蠑キ縺輔↓蠖ア髻ソ縺励∪縺吶\n螟ァ縺阪>縺サ縺ゥ螟牙ス「縺ョ謖ッ繧雁ケ縺悟、ァ縺阪¥縺ェ繧翫∪縺呻シ医≠繧薙∪繧雁、牙ス「縺励↑縺縺後∝、牙ス「縺吶k縺ィ縺阪ッ螟ァ縺阪¥螟牙ス「縺吶kシ") + ) self.simple_shape_maintenance_txt.Wrap(-1) self.simple_grid_sizer.Add(self.simple_shape_maintenance_txt, 0, wx.ALL, 5) @@ -1231,7 +1240,7 @@ def __init__( self.vertical_joint_mov_x_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)")) + self.vertical_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_x_min_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_x_min_txt, 0, wx.ALL, 5) @@ -1247,7 +1256,7 @@ def __init__( self.vertical_joint_mov_y_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)")) + self.vertical_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_y_min_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_y_min_txt, 0, wx.ALL, 5) @@ -1263,7 +1272,7 @@ def __init__( self.vertical_joint_mov_z_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)")) + self.vertical_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_z_min_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_z_min_txt, 0, wx.ALL, 5) @@ -1279,7 +1288,7 @@ def __init__( self.vertical_joint_mov_x_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)")) + self.vertical_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_x_max_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_x_max_txt, 0, wx.ALL, 5) @@ -1295,7 +1304,7 @@ def __init__( self.vertical_joint_mov_y_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)")) + self.vertical_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_y_max_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_y_max_txt, 0, wx.ALL, 5) @@ -1311,7 +1320,7 @@ def __init__( self.vertical_joint_mov_z_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)")) + self.vertical_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_joint_mov_z_max_txt.Wrap(-1) self.advance_vertical_joint_grid_sizer.Add(self.vertical_joint_mov_z_max_txt, 0, wx.ALL, 5) @@ -1562,7 +1571,7 @@ def __init__( self.horizonal_joint_mov_x_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)")) + self.horizonal_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_x_min_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_x_min_txt, 0, wx.ALL, 5) @@ -1578,7 +1587,7 @@ def __init__( self.horizonal_joint_mov_y_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)")) + self.horizonal_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_y_min_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_y_min_txt, 0, wx.ALL, 5) @@ -1594,7 +1603,7 @@ def __init__( self.horizonal_joint_mov_z_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)")) + self.horizonal_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_z_min_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_z_min_txt, 0, wx.ALL, 5) @@ -1610,7 +1619,7 @@ def __init__( self.horizonal_joint_mov_x_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)")) + self.horizonal_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_x_max_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_x_max_txt, 0, wx.ALL, 5) @@ -1626,7 +1635,7 @@ def __init__( self.horizonal_joint_mov_y_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)")) + self.horizonal_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_y_max_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_y_max_txt, 0, wx.ALL, 5) @@ -1642,7 +1651,7 @@ def __init__( self.horizonal_joint_mov_z_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)")) + self.horizonal_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_joint_mov_z_max_txt.Wrap(-1) self.advance_horizonal_joint_grid_sizer.Add(self.horizonal_joint_mov_z_max_txt, 0, wx.ALL, 5) @@ -1887,7 +1896,7 @@ def __init__( self.diagonal_joint_mov_x_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)")) + self.diagonal_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_x_min_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_x_min_txt, 0, wx.ALL, 5) @@ -1903,7 +1912,7 @@ def __init__( self.diagonal_joint_mov_y_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)")) + self.diagonal_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_y_min_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_y_min_txt, 0, wx.ALL, 5) @@ -1919,7 +1928,7 @@ def __init__( self.diagonal_joint_mov_z_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)")) + self.diagonal_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_z_min_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_z_min_txt, 0, wx.ALL, 5) @@ -1935,7 +1944,7 @@ def __init__( self.diagonal_joint_mov_x_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)")) + self.diagonal_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_x_max_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_x_max_txt, 0, wx.ALL, 5) @@ -1951,7 +1960,7 @@ def __init__( self.diagonal_joint_mov_y_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)")) + self.diagonal_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_y_max_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_y_max_txt, 0, wx.ALL, 5) @@ -1967,7 +1976,7 @@ def __init__( self.diagonal_joint_mov_z_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.diagonal_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)")) + self.diagonal_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.diagonal_joint_mov_z_max_txt.Wrap(-1) self.advance_diagonal_joint_grid_sizer.Add(self.diagonal_joint_mov_z_max_txt, 0, wx.ALL, 5) @@ -2220,7 +2229,7 @@ def __init__( self.vertical_reverse_joint_mov_x_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)")) + self.vertical_reverse_joint_mov_x_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_x_min_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_x_min_txt, 0, wx.ALL, 5) @@ -2236,7 +2245,7 @@ def __init__( self.vertical_reverse_joint_mov_y_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)")) + self.vertical_reverse_joint_mov_y_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_y_min_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_y_min_txt, 0, wx.ALL, 5) @@ -2252,7 +2261,7 @@ def __init__( self.vertical_reverse_joint_mov_z_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)")) + self.vertical_reverse_joint_mov_z_min_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_z_min_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_z_min_txt, 0, wx.ALL, 5) @@ -2268,7 +2277,7 @@ def __init__( self.vertical_reverse_joint_mov_x_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)")) + self.vertical_reverse_joint_mov_x_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_x_max_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_x_max_txt, 0, wx.ALL, 5) @@ -2284,7 +2293,7 @@ def __init__( self.vertical_reverse_joint_mov_y_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)")) + self.vertical_reverse_joint_mov_y_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_y_max_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_y_max_txt, 0, wx.ALL, 5) @@ -2300,7 +2309,7 @@ def __init__( self.vertical_reverse_joint_mov_z_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.vertical_reverse_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)")) + self.vertical_reverse_joint_mov_z_max_txt.SetToolTip(logger.transtext("譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.vertical_reverse_joint_mov_z_max_txt.Wrap(-1) self.advance_vertical_reverse_joint_grid_sizer.Add(self.vertical_reverse_joint_mov_z_max_txt, 0, wx.ALL, 5) @@ -2555,7 +2564,7 @@ def __init__( self.horizonal_reverse_joint_mov_x_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_x_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)")) + self.horizonal_reverse_joint_mov_x_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_x_min_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_x_min_txt, 0, wx.ALL, 5) @@ -2571,7 +2580,7 @@ def __init__( self.horizonal_reverse_joint_mov_y_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_y_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)")) + self.horizonal_reverse_joint_mov_y_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_y_min_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_y_min_txt, 0, wx.ALL, 5) @@ -2587,7 +2596,7 @@ def __init__( self.horizonal_reverse_joint_mov_z_min_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛蟆)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_z_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)")) + self.horizonal_reverse_joint_mov_z_min_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_z_min_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_z_min_txt, 0, wx.ALL, 5) @@ -2603,7 +2612,7 @@ def __init__( self.horizonal_reverse_joint_mov_x_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍氷(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_x_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)")) + self.horizonal_reverse_joint_mov_x_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_x_max_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_x_max_txt, 0, wx.ALL, 5) @@ -2619,7 +2628,7 @@ def __init__( self.horizonal_reverse_joint_mov_y_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍漂(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_y_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)")) + self.horizonal_reverse_joint_mov_y_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_y_max_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_y_max_txt, 0, wx.ALL, 5) @@ -2635,7 +2644,7 @@ def __init__( self.horizonal_reverse_joint_mov_z_max_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("遘サ蜍瓢(譛螟ァ)"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.horizonal_reverse_joint_mov_z_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)")) + self.horizonal_reverse_joint_mov_z_max_txt.SetToolTip(logger.transtext("讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮")) self.horizonal_reverse_joint_mov_z_max_txt.Wrap(-1) self.advance_horizonal_reverse_joint_grid_sizer.Add(self.horizonal_reverse_joint_mov_z_max_txt, 0, wx.ALL, 5) @@ -2914,17 +2923,17 @@ def __init__( self.joint_pos_type_txt = wx.StaticText( self.advance_window, wx.ID_ANY, logger.transtext("繧ク繝ァ繧、繝ウ繝井ス咲スョ"), wx.DefaultPosition, wx.DefaultSize, 0 ) - self.joint_pos_type_txt.SetToolTip(logger.transtext("繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧")) + self.joint_pos_type_txt.SetToolTip(logger.transtext("繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧")) self.joint_pos_type_txt.Wrap(-1) self.advance_option_grid_sizer.Add(self.joint_pos_type_txt, 0, wx.ALL, 5) self.joint_pos_type_ctrl = wx.Choice( self.advance_window, id=wx.ID_ANY, - choices=[logger.transtext("繝懊シ繝ウ髢"), logger.transtext("繝懊シ繝ウ菴咲スョ")], + choices=[logger.transtext("繝懊シ繝ウ菴咲スョ"), logger.transtext("繝懊シ繝ウ髢")], ) self.joint_pos_type_ctrl.SetToolTip(self.joint_pos_type_txt.GetToolTipText()) - self.joint_pos_type_ctrl.Bind(wx.EVT_CHOICE, self.main_frame.file_panel_ctrl.on_change_file) + self.joint_pos_type_ctrl.Bind(wx.EVT_CHOICE, self.on_change_joint_pos_type) self.advance_option_grid_sizer.Add(self.joint_pos_type_ctrl, 0, wx.ALL, 5) # 鬆らせ繝ォ繝シ繝域爾邏「謇区ウ輔ち繧、繝 @@ -2932,7 +2941,7 @@ def __init__( self.advance_window, wx.ID_ANY, logger.transtext("繝ォ繝シ繝域爾邏「"), wx.DefaultPosition, wx.DefaultSize, 0 ) self.route_search_type_txt.SetToolTip( - logger.transtext("譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈\n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ蜀遨阪r蜆ェ蜈") + logger.transtext("譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ隗貞コヲ蟾ョ繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈") ) self.route_search_type_txt.Wrap(-1) self.advance_option_grid_sizer.Add(self.route_search_type_txt, 0, wx.ALL, 5) @@ -2940,7 +2949,7 @@ def __init__( self.route_search_type_ctrl = wx.Choice( self.advance_window, id=wx.ID_ANY, - choices=[logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈"), logger.transtext("蜑埼らせ蜆ェ蜈")], + choices=[logger.transtext("蜑埼らせ蜆ェ蜈"), logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈")], ) self.route_search_type_ctrl.SetToolTip(self.route_search_type_txt.GetToolTipText()) self.route_search_type_ctrl.Bind(wx.EVT_CHOICE, self.main_frame.file_panel_ctrl.on_change_file) @@ -2951,7 +2960,7 @@ def __init__( self.advance_window, wx.ID_ANY, logger.transtext("譬ケ蜈鬆らせ謗ィ螳"), wx.DefaultPosition, wx.DefaultSize, 0 ) self.route_estimate_type_txt.SetToolTip( - logger.transtext("譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳") + logger.transtext("譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳喀n霆ク譁ケ蜷: 迚ゥ逅譁ケ蜷代ョ騾譁ケ蜷代r譬ケ蜈縺ィ縺励※謗ィ螳") ) self.route_estimate_type_txt.Wrap(-1) self.advance_option_grid_sizer.Add(self.route_estimate_type_txt, 0, wx.ALL, 5) @@ -2959,7 +2968,7 @@ def __init__( self.route_estimate_type_ctrl = wx.Choice( self.advance_window, id=wx.ID_ANY, - choices=[logger.transtext("隗貞コヲ"), logger.transtext("邵ョ蟆コ")], + choices=[logger.transtext("隗貞コヲ"), logger.transtext("邵ョ蟆コ"), logger.transtext("霆ク譁ケ蜷")], ) self.route_estimate_type_ctrl.SetToolTip(self.route_estimate_type_txt.GetToolTipText()) self.route_estimate_type_ctrl.Bind(wx.EVT_CHOICE, self.main_frame.file_panel_ctrl.on_change_file) @@ -3563,7 +3572,7 @@ def set_param_import_data(self, params: dict): self.horizonal_joint_spring_rot_x_spin.SetValue(params["horizonal_joint_spring_rot_x"]) self.horizonal_joint_spring_rot_y_spin.SetValue(params["horizonal_joint_spring_rot_y"]) self.horizonal_joint_spring_rot_z_spin.SetValue(params["horizonal_joint_spring_rot_z"]) - self.advance_horizonal_joint_restruct_check.SetValue(params.get("horizonal_joint_restruct", 1)) + self.advance_horizonal_joint_restruct_check.SetValue(params.get("horizonal_joint_restruct", 0)) self.advance_horizonal_joint_coefficient_spin.SetValue(params["horizonal_joint_coefficient"]) self.on_horizonal_joint(wx.EVT_CHECKBOX) @@ -4051,6 +4060,13 @@ def on_wheel_double_spin_ctrl(self, event: wx.Event, inc=0.1): self.main_frame.on_wheel_spin_ctrl(event, inc) self.main_frame.file_panel_ctrl.on_change_file(event) + def on_special_shape(self, event: wx.Event): + if self.simple_special_shape_ctrl.GetStringSelection() in [logger.transtext("蜈ィ縺ヲ陦ィ髱「")]: + # 縺吶∋縺ヲ陦ィ髱「縺ョ蝣エ蜷医∵耳螳壹r隗貞コヲ縺ォ蜀崎ィュ螳壹☆繧具シ医ョ繝輔か繝ォ繝医〒蜈・縺」縺ヲ縺繧九ッ縺壹□縺後∝ソオ縺ョ縺溘aシ + self.route_estimate_type_ctrl.SetStringSelection(logger.transtext("隗貞コヲ")) + self.route_search_type_ctrl.SetStringSelection(logger.transtext("蜑埼らせ蜆ェ蜈")) + self.main_frame.file_panel_ctrl.on_change_file(event) + def set_material_name(self, event: wx.Event): self.main_frame.file_panel_ctrl.on_change_file(event) # setValue縺ァ縺昴ョ縺セ縺セset_abb_name繧定オキ蜍輔☆繧 @@ -4122,13 +4138,13 @@ def set_abb_setting(self, event: wx.Event): self.physics_type_ctrl.SetStringSelection(abb_setting.get("physics_type", logger.transtext("蟶"))) if self.density_type_ctrl.GetStringSelection() == logger.transtext("鬆らせ"): self.density_type_ctrl.SetStringSelection(abb_setting.get("density_type", logger.transtext("鬆らせ"))) - if self.joint_pos_type_ctrl.GetStringSelection() == logger.transtext("繝懊シ繝ウ髢"): + if self.joint_pos_type_ctrl.GetStringSelection() == logger.transtext("繝懊シ繝ウ菴咲スョ"): self.joint_pos_type_ctrl.SetStringSelection( - abb_setting.get("joint_pos_type", logger.transtext("繝懊シ繝ウ髢")) + abb_setting.get("joint_pos_type", logger.transtext("繝懊シ繝ウ菴咲スョ")) ) - if self.route_search_type_ctrl.GetStringSelection() == logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈"): + if self.route_search_type_ctrl.GetStringSelection() == logger.transtext("蜑埼らせ蜆ェ蜈"): self.route_search_type_ctrl.SetStringSelection( - abb_setting.get("route_search_type", logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈")) + abb_setting.get("route_search_type", logger.transtext("蜑埼らせ蜆ェ蜈")) ) if self.route_estimate_type_ctrl.GetStringSelection() == logger.transtext("隗貞コヲ"): self.route_estimate_type_ctrl.SetStringSelection( @@ -4231,10 +4247,7 @@ def get_bone_grid(self): def set_mass(self, event: wx.Event): self.main_frame.file_panel_ctrl.on_change_file(event) - if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク"): - self.rigidbody_mass_spin.SetValue(self.simple_mass_slider.GetValue() / 30) - else: - self.rigidbody_mass_spin.SetValue(self.simple_mass_slider.GetValue()) + self.rigidbody_mass_spin.SetValue(self.simple_mass_slider.GetValue()) if self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("鬮ェ(繧キ繝ァ繝シ繝)"): self.rigidbody_coefficient_spin.SetValue(20 / self.simple_mass_slider.GetValue()) @@ -4250,11 +4263,11 @@ def set_mass(self, event: wx.Event): def set_simple_primitive(self, event: wx.Event): self.main_frame.file_panel_ctrl.on_change_file(event) self.advance_rigidbody_balancer_ctrl.SetValue(0) - self.advance_horizonal_joint_restruct_check.SetValue(1) + self.advance_horizonal_joint_restruct_check.SetValue(0) self.rigidbody_root_thicks_spin.SetValue(0.07) self.rigidbody_end_thicks_spin.SetValue(0.2) - self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ髢")) - self.route_search_type_ctrl.SetStringSelection(logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈")) + self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) + self.route_search_type_ctrl.SetStringSelection(logger.transtext("蜑埼らせ蜆ェ蜈")) self.route_estimate_type_ctrl.SetStringSelection(logger.transtext("隗貞コヲ")) self.advance_vertical_joint_valid_check.SetValue(1) @@ -4263,6 +4276,12 @@ def set_simple_primitive(self, event: wx.Event): self.advance_vertical_reverse_joint_valid_check.SetValue(0) self.advance_horizonal_reverse_joint_valid_check.SetValue(0) + self.advance_vertical_joint_coefficient_spin.SetValue(2.8) + self.advance_horizonal_joint_coefficient_spin.SetValue(4.2) + self.advance_diagonal_joint_coefficient_spin.SetValue(1) + self.advance_vertical_reverse_joint_coefficient_spin.SetValue(1) + self.advance_horizonal_reverse_joint_coefficient_spin.SetValue(1) + if logger.transtext("蜊倅ク謠コ繧檎黄") in self.simple_primitive_ctrl.GetStringSelection(): self.physics_type_ctrl.SetStringSelection(logger.transtext("蜊倅ク謠コ")) self.advance_rigidbody_shape_type_ctrl.SetStringSelection(logger.transtext("繧ォ繝励そ繝ォ")) @@ -4289,58 +4308,65 @@ def set_simple_primitive(self, event: wx.Event): self.parent_type_ctrl.SetStringSelection(logger.transtext("荳ュ蠢")) if self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繧ウ繝繝医Φ)"): - self.simple_mass_slider.SetValue(1.3) - self.simple_air_resistance_slider.SetValue(1.7) - self.simple_shape_maintenance_slider.SetValue(2.2) + self.simple_mass_slider.SetValue(3.2) + self.simple_air_resistance_slider.SetValue(1.5) + self.simple_shape_maintenance_slider.SetValue(1.5) + + self.advance_horizonal_joint_valid_check.SetValue(1) + + if self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繧ヲ繝シ繝ォ)"): + self.simple_mass_slider.SetValue(6.2) + self.simple_air_resistance_slider.SetValue(3.5) + self.simple_shape_maintenance_slider.SetValue(0.6) self.advance_horizonal_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繧キ繝ォ繧ッ)"): - self.simple_mass_slider.SetValue(0.8) - self.simple_air_resistance_slider.SetValue(1.2) - self.simple_shape_maintenance_slider.SetValue(1.7) + self.simple_mass_slider.SetValue(1.8) + self.simple_air_resistance_slider.SetValue(0.9) + self.simple_shape_maintenance_slider.SetValue(0.2) self.advance_horizonal_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繝吶Ν繝吶ャ繝)"): - self.simple_mass_slider.SetValue(2.0) - self.simple_air_resistance_slider.SetValue(1.4) - self.simple_shape_maintenance_slider.SetValue(1.9) + self.simple_mass_slider.SetValue(5.5) + self.simple_air_resistance_slider.SetValue(1.1) + self.simple_shape_maintenance_slider.SetValue(3.3) self.advance_horizonal_joint_valid_check.SetValue(1) self.advance_diagonal_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繝ャ繧カ繝シ)"): - self.simple_mass_slider.SetValue(2.2) - self.simple_air_resistance_slider.SetValue(1.9) - self.simple_shape_maintenance_slider.SetValue(3.6) + self.simple_mass_slider.SetValue(6) + self.simple_air_resistance_slider.SetValue(1.5) + self.simple_shape_maintenance_slider.SetValue(2.5) self.advance_horizonal_joint_valid_check.SetValue(1) self.advance_diagonal_joint_valid_check.SetValue(1) - self.advance_vertical_reverse_joint_valid_check.SetValue(1) - self.advance_horizonal_reverse_joint_valid_check.SetValue(1) + # self.advance_vertical_reverse_joint_valid_check.SetValue(1) + # self.advance_horizonal_reverse_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蟶(繝繝九Β)"): - self.simple_mass_slider.SetValue(1.9) - self.simple_air_resistance_slider.SetValue(3.3) - self.simple_shape_maintenance_slider.SetValue(2.3) + self.simple_mass_slider.SetValue(7) + self.simple_air_resistance_slider.SetValue(3.5) + self.simple_shape_maintenance_slider.SetValue(2.0) self.advance_horizonal_joint_valid_check.SetValue(1) self.advance_diagonal_joint_valid_check.SetValue(1) - self.advance_vertical_reverse_joint_valid_check.SetValue(1) - self.advance_horizonal_reverse_joint_valid_check.SetValue(1) + # self.advance_vertical_reverse_joint_valid_check.SetValue(1) + # self.advance_horizonal_reverse_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("蜊倅ク謠コ繧檎黄"): - self.simple_mass_slider.SetValue(1.3) + self.simple_mass_slider.SetValue(3.3) self.simple_air_resistance_slider.SetValue(2.5) self.simple_shape_maintenance_slider.SetValue(2.8) self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("鬮ェ(繧キ繝ァ繝シ繝)"): - self.simple_mass_slider.SetValue(0.8) - self.simple_air_resistance_slider.SetValue(3.2) - self.simple_shape_maintenance_slider.SetValue(4.2) - self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) + + self.simple_mass_slider.SetValue(2) + self.simple_air_resistance_slider.SetValue(2) + self.simple_shape_maintenance_slider.SetValue(1.6) self.advance_vertical_joint_coefficient_spin.SetValue(1.0) @@ -4349,33 +4375,39 @@ def set_simple_primitive(self, event: wx.Event): elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("鬮ェ(繝ュ繝ウ繧ー)"): self.simple_mass_slider.SetValue(1.2) - self.simple_air_resistance_slider.SetValue(2.3) - self.simple_shape_maintenance_slider.SetValue(3.5) + self.simple_air_resistance_slider.SetValue(2.8) + self.simple_shape_maintenance_slider.SetValue(1.6) self.advance_vertical_joint_coefficient_spin.SetValue(1.0) - self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("鬮ェ(繧「繝帶ッ)"): - self.simple_mass_slider.SetValue(1.2) - self.simple_air_resistance_slider.SetValue(2.7) - self.simple_shape_maintenance_slider.SetValue(3.8) + self.simple_mass_slider.SetValue(2.2) + self.simple_air_resistance_slider.SetValue(0.2) + self.simple_shape_maintenance_slider.SetValue(1.5) self.advance_vertical_joint_coefficient_spin.SetValue(1.0) self.advance_rigidbody_balancer_ctrl.SetValue(1) - self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("閭ク(蟆)"): - self.simple_mass_slider.SetValue(5.4) - self.simple_air_resistance_slider.SetValue(4.3) - self.simple_shape_maintenance_slider.SetValue(3.7) + self.simple_mass_slider.SetValue(4.0) + self.simple_air_resistance_slider.SetValue(1.5) + self.simple_shape_maintenance_slider.SetValue(3.0) + + self.advance_vertical_joint_coefficient_spin.SetValue(1.0) + self.advance_horizonal_joint_coefficient_spin.SetValue(1.0) + self.advance_diagonal_joint_coefficient_spin.SetValue(1.0) self.advance_horizonal_joint_valid_check.SetValue(1) self.advance_diagonal_joint_valid_check.SetValue(1) elif self.simple_primitive_ctrl.GetStringSelection() == logger.transtext("閭ク(螟ァ)"): self.simple_mass_slider.SetValue(6.2) - self.simple_air_resistance_slider.SetValue(3.3) - self.simple_shape_maintenance_slider.SetValue(3.0) + self.simple_air_resistance_slider.SetValue(1.2) + self.simple_shape_maintenance_slider.SetValue(2.6) + + self.advance_vertical_joint_coefficient_spin.SetValue(1.0) + self.advance_horizonal_joint_coefficient_spin.SetValue(1.0) + self.advance_diagonal_joint_coefficient_spin.SetValue(1.0) self.advance_horizonal_joint_valid_check.SetValue(1) self.advance_diagonal_joint_valid_check.SetValue(1) @@ -4387,6 +4419,11 @@ def set_simple_primitive(self, event: wx.Event): self.on_vertical_reverse_joint(event) self.on_horizonal_reverse_joint(event) + def on_change_joint_pos_type(self, event: wx.Event): + self.main_frame.file_panel_ctrl.on_change_file(event) + # 繧ク繝ァ繧、繝ウ繝域磁邯壽婿豕輔′螟峨o縺」縺溘i繧ク繝ァ繧、繝ウ繝亥、繧ょ、画峩縺吶k + self.set_mass(event) + def set_air_resistance(self, event: wx.Event): self.main_frame.file_panel_ctrl.on_change_file(event) # 雉ェ驥上↓蠢懊§縺ヲ貂幄。ー繧定ィュ螳 @@ -4463,206 +4500,307 @@ def set_air_resistance(self, event: wx.Event): def set_shape_maintenance(self, event: wx.Event): self.main_frame.file_panel_ctrl.on_change_file(event) + mass_coefficient = max(1, self.simple_mass_slider.GetValue() * 0.5) + + # 譟斐i縺九& + air_resistance_ratio = ( + self.simple_air_resistance_slider.GetValue() / self.simple_air_resistance_slider.GetMax() + ) + # 蠑オ繧 + shape_maintenance_ratio = ( + self.simple_shape_maintenance_slider.GetValue() / self.simple_shape_maintenance_slider.GetMax() + ) + + # 邵ヲ繧ク繝ァ繧、繝ウ繝 + self.advance_vertical_joint_coefficient_spin.SetValue(air_resistance_ratio * 10) - if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク"): - # 閭ク縺ョ蝣エ蜷医∫音谿翫ず繝ァ繧、繝ウ繝郁ィュ螳 - air_resistance_ratio = ( - self.simple_air_resistance_slider.GetMax() / self.simple_air_resistance_slider.GetValue() + vertical_joint_ratio = 5.5 if logger.transtext("閭ク") in self.physics_type_ctrl.GetStringSelection() else 1 + + vertical_joint_rot = ( + max( + 0, + min( + 180, + ( + 180 + - air_resistance_ratio + * 180 + * self.get_joint_coefficient(vertical_joint_ratio, is_reverse=True) + ), + ), ) - shape_maintenance_ratio = ( - self.simple_shape_maintenance_slider.GetMax() / self.simple_shape_maintenance_slider.GetValue() + if air_resistance_ratio < 1 + else 0 + ) + vertical_joint_y_rot = ( + max( + 0, + min( + 89, + ( + 89 + - air_resistance_ratio * 89 * self.get_joint_coefficient(vertical_joint_ratio, is_reverse=True) + ), + ), ) + if air_resistance_ratio < 1 + else 0 + ) - self.vertical_joint_rot_x_min_spin.SetValue(-(air_resistance_ratio * 8)) - self.vertical_joint_rot_x_max_spin.SetValue(air_resistance_ratio) - self.vertical_joint_rot_y_min_spin.SetValue(-(air_resistance_ratio)) - self.vertical_joint_rot_y_max_spin.SetValue(air_resistance_ratio) - self.vertical_joint_rot_z_min_spin.SetValue(0) - self.vertical_joint_rot_z_max_spin.SetValue(0) - - self.vertical_joint_spring_rot_x_spin.SetValue(shape_maintenance_ratio * 20) - self.vertical_joint_spring_rot_y_spin.SetValue(shape_maintenance_ratio * 40) - self.vertical_joint_spring_rot_z_spin.SetValue(0) - - self.horizonal_joint_rot_x_min_spin.SetValue(-(air_resistance_ratio * 8)) - self.horizonal_joint_rot_x_max_spin.SetValue(air_resistance_ratio * 8) - self.horizonal_joint_rot_y_min_spin.SetValue(0) - self.horizonal_joint_rot_y_max_spin.SetValue(0) - self.horizonal_joint_rot_z_min_spin.SetValue(0) - self.horizonal_joint_rot_z_max_spin.SetValue(0) - - self.horizonal_joint_spring_rot_x_spin.SetValue(0) - self.horizonal_joint_spring_rot_y_spin.SetValue(0) - self.horizonal_joint_spring_rot_z_spin.SetValue(0) - - self.diagonal_joint_rot_x_min_spin.SetValue(-(air_resistance_ratio * 10)) - self.diagonal_joint_rot_x_max_spin.SetValue((air_resistance_ratio * 10)) - self.diagonal_joint_rot_y_min_spin.SetValue(0) - self.diagonal_joint_rot_y_max_spin.SetValue(0) - self.diagonal_joint_rot_z_min_spin.SetValue(0) - self.diagonal_joint_rot_z_max_spin.SetValue(0) - - self.diagonal_joint_spring_rot_x_spin.SetValue(shape_maintenance_ratio * 40) - self.diagonal_joint_spring_rot_y_spin.SetValue(shape_maintenance_ratio * 20) - self.diagonal_joint_spring_rot_z_spin.SetValue(0) + # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ + vertical_joint_rot = 2 if not vertical_joint_rot else vertical_joint_rot + vertical_joint_y_rot = 2 if not vertical_joint_y_rot else vertical_joint_y_rot + vertical_spring_rot_ratio = 10 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 200 + vertical_spring_y_rot_ratio = ( + 5 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 100 + ) + + vertical_spring_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(vertical_spring_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) + vertical_spring_y_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(vertical_spring_y_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) + + if self.physics_type_ctrl.GetStringSelection() == logger.transtext("鬮ェ"): + # 鬮ェ縺ョ豈帙ョ蝣エ蜷医√ず繝ァ繧、繝ウ繝医ョ蛻カ髯舌ッ縺阪▽繧√↓繝サ縺ー縺ュ蛟、繧貞ー上&繧√↓縺励※縺翫¥ + vertical_joint_rot /= 1.2 + vertical_spring_rot /= 2.5 + vertical_spring_y_rot /= 2.5 + + self.vertical_joint_rot_x_min_spin.SetValue(-vertical_joint_rot) + self.vertical_joint_rot_x_max_spin.SetValue(vertical_joint_rot) + self.vertical_joint_rot_y_min_spin.SetValue(-vertical_joint_y_rot) + self.vertical_joint_rot_y_max_spin.SetValue(vertical_joint_y_rot) + self.vertical_joint_rot_z_min_spin.SetValue(-vertical_joint_rot) + self.vertical_joint_rot_z_max_spin.SetValue(vertical_joint_rot) + + self.vertical_joint_spring_rot_x_spin.SetValue(vertical_spring_rot) + self.vertical_joint_spring_rot_y_spin.SetValue(vertical_spring_y_rot) + self.vertical_joint_spring_rot_z_spin.SetValue(vertical_spring_rot) + + # 讓ェ繧ク繝ァ繧、繝ウ繝 + if logger.transtext("閭ク") in self.physics_type_ctrl.GetStringSelection(): + self.horizonal_joint_mov_y_min_spin.SetValue(0) + self.horizonal_joint_mov_y_max_spin.SetValue(0) else: - # 雉ェ驥 - mass_ratio = self.simple_mass_slider.GetValue() / self.simple_mass_slider.GetMax() - # 蠑オ繧 - shape_maintenance_ratio = ( - self.simple_shape_maintenance_slider.GetValue() / self.simple_shape_maintenance_slider.GetMax() + horizonal_joint_mov = max(0, (1 - air_resistance_ratio) * 0.5) + self.horizonal_joint_mov_y_min_spin.SetValue(-horizonal_joint_mov) + self.horizonal_joint_mov_y_max_spin.SetValue(horizonal_joint_mov / 2) + + self.advance_horizonal_joint_coefficient_spin.SetValue(air_resistance_ratio * 20) + + horizonal_joint_ratio = 4 if logger.transtext("閭ク") in self.physics_type_ctrl.GetStringSelection() else 1.2 + + horizonal_joint_rot = ( + max( + 0, + min( + 180, + ( + 180 + - air_resistance_ratio + * 180 + * self.get_joint_coefficient(horizonal_joint_ratio, is_reverse=True) + ), + ), ) - # 譟斐i縺九& - air_resistance_ratio = ( - self.simple_air_resistance_slider.GetValue() / self.simple_air_resistance_slider.GetMax() + if air_resistance_ratio < 1 + else 0 + ) + horizonal_joint_y_rot = ( + max( + 0, + min( + 89, + ( + 89 + - air_resistance_ratio + * 89 + * self.get_joint_coefficient(horizonal_joint_ratio, is_reverse=True) + ), + ), ) + if air_resistance_ratio < 1 + else 0 + ) - # 邵ヲ繧ク繝ァ繧、繝ウ繝 - base_vertical_ratio = air_resistance_ratio * shape_maintenance_ratio - if self.physics_type_ctrl.GetStringSelection() != logger.transtext("鬮ェ"): - self.advance_vertical_joint_coefficient_spin.SetValue(base_vertical_ratio * 10) - - vertical_joint_rot = max(0, min(180, (180 - base_vertical_ratio * 180 * 1.5))) - vertical_joint_y_rot = max(0, min(89, (89 - base_vertical_ratio * 89 * 1.5))) - - # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ - vertical_joint_rot = 2 if not vertical_joint_rot else vertical_joint_rot - vertical_joint_y_rot = 2 if not vertical_joint_y_rot else vertical_joint_y_rot - - vertical_spring_rot = max(0, min(180, base_vertical_ratio * 180 * 2)) - vertical_spring_y_rot = max(0, min(89, base_vertical_ratio * 89 * 2)) - - if self.physics_type_ctrl.GetStringSelection() == logger.transtext("鬮ェ"): - # 鬮ェ縺ョ豈帙ョ蝣エ蜷医√ず繝ァ繧、繝ウ繝医ョ蛻カ髯舌ッ縺阪▽繧√↓繝サ縺ー縺ュ蛟、繧貞ー上&繧√↓縺励※縺翫¥ - vertical_joint_rot /= 1.2 - vertical_joint_y_rot /= 1.2 - vertical_spring_rot /= 3 - vertical_spring_y_rot /= 3 - - self.vertical_joint_rot_x_min_spin.SetValue(-vertical_joint_rot) - self.vertical_joint_rot_x_max_spin.SetValue(vertical_joint_rot) - self.vertical_joint_rot_y_min_spin.SetValue(-vertical_joint_y_rot) - self.vertical_joint_rot_y_max_spin.SetValue(vertical_joint_y_rot) - self.vertical_joint_rot_z_min_spin.SetValue(-vertical_joint_rot) - self.vertical_joint_rot_z_max_spin.SetValue(vertical_joint_rot) - - self.vertical_joint_spring_rot_x_spin.SetValue(vertical_spring_rot) - self.vertical_joint_spring_rot_y_spin.SetValue(vertical_spring_y_rot) - self.vertical_joint_spring_rot_z_spin.SetValue(vertical_spring_rot) - - # 讓ェ繧ク繝ァ繧、繝ウ繝 - base_horizonal_ratio = shape_maintenance_ratio * mass_ratio - horizonal_joint_mov = 1 - base_horizonal_ratio * 3 - self.horizonal_joint_mov_y_max_spin.SetValue(horizonal_joint_mov) - - if self.physics_type_ctrl.GetStringSelection() != logger.transtext("鬮ェ"): - self.advance_horizonal_joint_coefficient_spin.SetValue(base_horizonal_ratio * 20) - - horizonal_joint_rot = max(0, min(180, (180 - base_horizonal_ratio * 180 * 2))) - horizonal_joint_y_rot = max(0, min(89, (89 - base_horizonal_ratio * 89 * 2))) - - # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ - horizonal_joint_rot = 2 if not horizonal_joint_rot else horizonal_joint_rot - horizonal_joint_y_rot = 2 if not horizonal_joint_y_rot else horizonal_joint_y_rot - - horizonal_spring_rot = max(0, min(180, base_horizonal_ratio * 180 * 2)) - horizonal_spring_y_rot = max(0, min(89, base_horizonal_ratio * 89 * 2)) - - self.horizonal_joint_rot_x_min_spin.SetValue(-horizonal_joint_rot) - self.horizonal_joint_rot_x_max_spin.SetValue(horizonal_joint_rot) - self.horizonal_joint_rot_y_min_spin.SetValue(-horizonal_joint_y_rot) - self.horizonal_joint_rot_y_max_spin.SetValue(horizonal_joint_y_rot) - self.horizonal_joint_rot_z_min_spin.SetValue(-horizonal_joint_rot) - self.horizonal_joint_rot_z_max_spin.SetValue(horizonal_joint_rot) - - self.horizonal_joint_spring_rot_x_spin.SetValue(horizonal_spring_rot) - self.horizonal_joint_spring_rot_y_spin.SetValue(horizonal_spring_y_rot) - self.horizonal_joint_spring_rot_z_spin.SetValue(horizonal_spring_rot) - - # 譁懊a繧ク繝ァ繧、繝ウ繝 - base_diagonal_ratio = air_resistance_ratio * mass_ratio - if self.physics_type_ctrl.GetStringSelection() != logger.transtext("鬮ェ"): - self.advance_diagonal_joint_coefficient_spin.SetValue(base_diagonal_ratio * 10) - - diagonal_joint_rot = max(0, min(180, (180 - base_diagonal_ratio * 180 * 2))) - diagonal_joint_y_rot = max(0, min(89, (89 - base_diagonal_ratio * 89 * 2))) - - # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ - diagonal_joint_rot = 2 if not diagonal_joint_rot else diagonal_joint_rot - diagonal_joint_y_rot = 2 if not diagonal_joint_y_rot else diagonal_joint_y_rot - - diagonal_spring_rot = max(0, min(180, base_diagonal_ratio * 180 * 2)) - diagonal_spring_y_rot = max(0, min(89, base_diagonal_ratio * 89 * 2)) - - self.diagonal_joint_rot_x_min_spin.SetValue(-diagonal_joint_rot) - self.diagonal_joint_rot_x_max_spin.SetValue(diagonal_joint_rot) - self.diagonal_joint_rot_y_min_spin.SetValue(-diagonal_joint_y_rot) - self.diagonal_joint_rot_y_max_spin.SetValue(diagonal_joint_y_rot) - self.diagonal_joint_rot_z_min_spin.SetValue(-diagonal_joint_rot) - self.diagonal_joint_rot_z_max_spin.SetValue(diagonal_joint_rot) - - self.diagonal_joint_spring_rot_x_spin.SetValue(diagonal_spring_rot) - self.diagonal_joint_spring_rot_y_spin.SetValue(diagonal_spring_y_rot) - self.diagonal_joint_spring_rot_z_spin.SetValue(diagonal_spring_rot) - - # 邵ヲ騾繧ク繝ァ繧、繝ウ繝 - self.advance_vertical_reverse_joint_coefficient_spin.SetValue( - self.advance_vertical_joint_coefficient_spin.GetValue() - ) + # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ + horizonal_joint_rot = 2 if not horizonal_joint_rot else horizonal_joint_rot + horizonal_joint_y_rot = 2 if not horizonal_joint_y_rot else horizonal_joint_y_rot - self.vertical_reverse_joint_mov_y_max_spin.SetValue(self.vertical_joint_mov_y_max_spin.GetValue()) + horizonal_spring_rot_ratio = ( + 10 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 300 + ) + horizonal_spring_y_rot_ratio = ( + 5 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 200 + ) - self.vertical_reverse_joint_rot_x_min_spin.SetValue(self.vertical_joint_rot_x_min_spin.GetValue()) - self.vertical_reverse_joint_rot_x_max_spin.SetValue(self.vertical_joint_rot_x_max_spin.GetValue()) - self.vertical_reverse_joint_rot_y_min_spin.SetValue(self.vertical_joint_rot_y_min_spin.GetValue()) - self.vertical_reverse_joint_rot_y_max_spin.SetValue(self.vertical_joint_rot_y_max_spin.GetValue()) - self.vertical_reverse_joint_rot_z_min_spin.SetValue(self.vertical_joint_rot_z_min_spin.GetValue()) - self.vertical_reverse_joint_rot_z_max_spin.SetValue(self.vertical_joint_rot_z_max_spin.GetValue()) + horizonal_spring_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(horizonal_spring_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) + horizonal_spring_y_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(horizonal_spring_y_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) + + self.horizonal_joint_rot_x_min_spin.SetValue(-horizonal_joint_rot) + self.horizonal_joint_rot_x_max_spin.SetValue(horizonal_joint_rot) + self.horizonal_joint_rot_y_min_spin.SetValue(-horizonal_joint_y_rot) + self.horizonal_joint_rot_y_max_spin.SetValue(horizonal_joint_y_rot) + self.horizonal_joint_rot_z_min_spin.SetValue(-horizonal_joint_rot) + self.horizonal_joint_rot_z_max_spin.SetValue(horizonal_joint_rot) + + self.horizonal_joint_spring_rot_x_spin.SetValue(horizonal_spring_rot) + self.horizonal_joint_spring_rot_y_spin.SetValue(horizonal_spring_y_rot) + self.horizonal_joint_spring_rot_z_spin.SetValue(horizonal_spring_rot) - self.vertical_reverse_joint_spring_rot_x_spin.SetValue(self.vertical_joint_spring_rot_x_spin.GetValue()) - self.vertical_reverse_joint_spring_rot_y_spin.SetValue(self.vertical_joint_spring_rot_y_spin.GetValue()) - self.vertical_reverse_joint_spring_rot_z_spin.SetValue(self.vertical_joint_spring_rot_z_spin.GetValue()) + # 譁懊a繧ク繝ァ繧、繝ウ繝 + if logger.transtext("閭ク") in self.physics_type_ctrl.GetStringSelection(): + self.diagonal_joint_mov_y_min_spin.SetValue(0) + self.diagonal_joint_mov_y_max_spin.SetValue(0) + else: + diagonal_joint_mov = max(0, (1 - air_resistance_ratio) * 0.7) + self.diagonal_joint_mov_y_min_spin.SetValue(-diagonal_joint_mov) + self.diagonal_joint_mov_y_max_spin.SetValue(diagonal_joint_mov / 2) + + self.advance_diagonal_joint_coefficient_spin.SetValue(air_resistance_ratio * 10) - # 讓ェ騾繧ク繝ァ繧、繝ウ繝 - self.horizonal_reverse_joint_mov_x_min_spin.SetValue(self.horizonal_joint_mov_x_min_spin.GetValue()) - self.horizonal_reverse_joint_mov_x_max_spin.SetValue(self.horizonal_joint_mov_x_max_spin.GetValue()) + diagonal_joint_ratio = 5 if logger.transtext("閭ク") in self.physics_type_ctrl.GetStringSelection() else 1.5 - self.advance_horizonal_reverse_joint_coefficient_spin.SetValue( - self.advance_horizonal_joint_coefficient_spin.GetValue() + diagonal_joint_rot = ( + max( + 0, + min( + 180, + ( + 180 + - air_resistance_ratio + * 180 + * self.get_joint_coefficient(diagonal_joint_ratio, is_reverse=True) + ), + ), + ) + if air_resistance_ratio < 1 + else 0 + ) + diagonal_joint_y_rot = ( + max( + 0, + min( + 89, + ( + 89 + - air_resistance_ratio * 89 * self.get_joint_coefficient(diagonal_joint_ratio, is_reverse=True) + ), + ), ) + if air_resistance_ratio < 1 + else 0 + ) - self.horizonal_reverse_joint_mov_y_max_spin.SetValue(self.horizonal_joint_mov_y_max_spin.GetValue()) + # 蛻カ髯占ァ貞コヲ縺0縺ョ蝣エ蜷医√■繧縺」縺ィ縺縺大虚縺九☆ + diagonal_joint_rot = 2 if not diagonal_joint_rot else diagonal_joint_rot + diagonal_joint_y_rot = 2 if not diagonal_joint_y_rot else diagonal_joint_y_rot - self.horizonal_reverse_joint_rot_x_min_spin.SetValue(self.horizonal_joint_rot_x_min_spin.GetValue()) - self.horizonal_reverse_joint_rot_x_max_spin.SetValue(self.horizonal_joint_rot_x_max_spin.GetValue()) - self.horizonal_reverse_joint_rot_y_min_spin.SetValue(self.horizonal_joint_rot_y_min_spin.GetValue()) - self.horizonal_reverse_joint_rot_y_max_spin.SetValue(self.horizonal_joint_rot_y_max_spin.GetValue()) - self.horizonal_reverse_joint_rot_z_min_spin.SetValue(self.horizonal_joint_rot_z_min_spin.GetValue()) - self.horizonal_reverse_joint_rot_z_max_spin.SetValue(self.horizonal_joint_rot_z_max_spin.GetValue()) + diagonal_spring_rot_ratio = 10 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 300 + diagonal_spring_y_rot_ratio = ( + 5 if self.physics_type_ctrl.GetStringSelection() == logger.transtext("閭ク") else 200 + ) - self.horizonal_reverse_joint_spring_rot_x_spin.SetValue(self.horizonal_joint_spring_rot_x_spin.GetValue()) - self.horizonal_reverse_joint_spring_rot_y_spin.SetValue(self.horizonal_joint_spring_rot_y_spin.GetValue()) - self.horizonal_reverse_joint_spring_rot_z_spin.SetValue(self.horizonal_joint_spring_rot_z_spin.GetValue()) + diagonal_spring_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(diagonal_spring_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) + diagonal_spring_y_rot = ( + shape_maintenance_ratio * self.get_joint_coefficient(diagonal_spring_y_rot_ratio) * mass_coefficient + if shape_maintenance_ratio < 1 + else 0 + ) - if self.simple_shape_maintenance_slider.GetValue() > self.simple_shape_maintenance_slider.GetMax() * 0.6: - # 荳螳壻サ・荳翫ョ邯ュ謖∵─縺ァ縺ゅl縺ー譁懊a繧ょシオ繧 - if logger.transtext("蟶") in self.simple_material_ctrl.GetStringSelection(): - # 譁懊a縺ッ蟶縺ョ縺ソ - self.advance_diagonal_joint_valid_check.SetValue(1) - # 荳蠎ヲ蠑オ縺」縺溘i繝√ぉ繝繧ッ縺ッ閾ェ蜍輔〒螟悶&縺ェ縺 + self.diagonal_joint_rot_x_min_spin.SetValue(-diagonal_joint_rot) + self.diagonal_joint_rot_x_max_spin.SetValue(diagonal_joint_rot) + self.diagonal_joint_rot_y_min_spin.SetValue(-diagonal_joint_y_rot) + self.diagonal_joint_rot_y_max_spin.SetValue(diagonal_joint_y_rot) + self.diagonal_joint_rot_z_min_spin.SetValue(-diagonal_joint_rot) + self.diagonal_joint_rot_z_max_spin.SetValue(diagonal_joint_rot) - if ( - self.physics_type_ctrl.GetStringSelection() == logger.transtext("蟶") - and self.simple_shape_maintenance_slider.GetValue() - > self.simple_shape_maintenance_slider.GetMax() * 0.8 - ): - # 荳螳壻サ・荳翫ョ邯ュ謖∵─縺ァ縺ゅl縺ー騾繧ょシオ繧 - self.advance_vertical_reverse_joint_valid_check.SetValue(1) - self.advance_horizonal_reverse_joint_valid_check.SetValue(1) + self.diagonal_joint_spring_rot_x_spin.SetValue(diagonal_spring_rot) + self.diagonal_joint_spring_rot_y_spin.SetValue(diagonal_spring_y_rot) + self.diagonal_joint_spring_rot_z_spin.SetValue(diagonal_spring_rot) + + # 邵ヲ騾繧ク繝ァ繧、繝ウ繝 + self.advance_vertical_reverse_joint_coefficient_spin.SetValue( + self.advance_vertical_joint_coefficient_spin.GetValue() + ) + + self.vertical_reverse_joint_mov_y_min_spin.SetValue(self.vertical_joint_mov_y_min_spin.GetValue()) + self.vertical_reverse_joint_mov_y_max_spin.SetValue(self.vertical_joint_mov_y_max_spin.GetValue()) + + self.vertical_reverse_joint_rot_x_min_spin.SetValue(self.vertical_joint_rot_x_min_spin.GetValue()) + self.vertical_reverse_joint_rot_x_max_spin.SetValue(self.vertical_joint_rot_x_max_spin.GetValue()) + self.vertical_reverse_joint_rot_y_min_spin.SetValue(self.vertical_joint_rot_y_min_spin.GetValue()) + self.vertical_reverse_joint_rot_y_max_spin.SetValue(self.vertical_joint_rot_y_max_spin.GetValue()) + self.vertical_reverse_joint_rot_z_min_spin.SetValue(self.vertical_joint_rot_z_min_spin.GetValue()) + self.vertical_reverse_joint_rot_z_max_spin.SetValue(self.vertical_joint_rot_z_max_spin.GetValue()) + + self.vertical_reverse_joint_spring_rot_x_spin.SetValue(self.vertical_joint_spring_rot_x_spin.GetValue()) + self.vertical_reverse_joint_spring_rot_y_spin.SetValue(self.vertical_joint_spring_rot_y_spin.GetValue()) + self.vertical_reverse_joint_spring_rot_z_spin.SetValue(self.vertical_joint_spring_rot_z_spin.GetValue()) + + # 讓ェ騾繧ク繝ァ繧、繝ウ繝 + self.horizonal_reverse_joint_mov_x_min_spin.SetValue(self.horizonal_joint_mov_x_min_spin.GetValue()) + self.horizonal_reverse_joint_mov_x_max_spin.SetValue(self.horizonal_joint_mov_x_max_spin.GetValue()) + + self.advance_horizonal_reverse_joint_coefficient_spin.SetValue( + self.advance_horizonal_joint_coefficient_spin.GetValue() + ) + + self.horizonal_reverse_joint_mov_y_min_spin.SetValue(self.horizonal_joint_mov_y_min_spin.GetValue()) + self.horizonal_reverse_joint_mov_y_max_spin.SetValue(self.horizonal_joint_mov_y_max_spin.GetValue()) + + self.horizonal_reverse_joint_rot_x_min_spin.SetValue(self.horizonal_joint_rot_x_min_spin.GetValue()) + self.horizonal_reverse_joint_rot_x_max_spin.SetValue(self.horizonal_joint_rot_x_max_spin.GetValue()) + self.horizonal_reverse_joint_rot_y_min_spin.SetValue(self.horizonal_joint_rot_y_min_spin.GetValue()) + self.horizonal_reverse_joint_rot_y_max_spin.SetValue(self.horizonal_joint_rot_y_max_spin.GetValue()) + self.horizonal_reverse_joint_rot_z_min_spin.SetValue(self.horizonal_joint_rot_z_min_spin.GetValue()) + self.horizonal_reverse_joint_rot_z_max_spin.SetValue(self.horizonal_joint_rot_z_max_spin.GetValue()) + + self.horizonal_reverse_joint_spring_rot_x_spin.SetValue(self.horizonal_joint_spring_rot_x_spin.GetValue()) + self.horizonal_reverse_joint_spring_rot_y_spin.SetValue(self.horizonal_joint_spring_rot_y_spin.GetValue()) + self.horizonal_reverse_joint_spring_rot_z_spin.SetValue(self.horizonal_joint_spring_rot_z_spin.GetValue()) + + if self.simple_shape_maintenance_slider.GetValue() > self.simple_shape_maintenance_slider.GetMax() * 0.7: + # 荳螳壻サ・荳翫ョ邯ュ謖∵─縺ァ縺ゅl縺ー譁懊a繧ょシオ繧 + if logger.transtext("蟶") in self.simple_material_ctrl.GetStringSelection(): + # 譁懊a縺ッ蟶縺ョ縺ソ + self.advance_diagonal_joint_valid_check.SetValue(1) + # 荳蠎ヲ蠑オ縺」縺溘i繝√ぉ繝繧ッ縺ッ閾ェ蜍輔〒螟悶&縺ェ縺 + + if ( + self.physics_type_ctrl.GetStringSelection() == logger.transtext("蟶") + and self.simple_shape_maintenance_slider.GetValue() > self.simple_shape_maintenance_slider.GetMax() * 0.9 + ): + # 荳螳壻サ・荳翫ョ邯ュ謖∵─縺ァ縺ゅl縺ー騾繧ょシオ繧 + self.advance_vertical_reverse_joint_valid_check.SetValue(1) + self.advance_horizonal_reverse_joint_valid_check.SetValue(1) + + self.on_diagonal_joint(event) + self.on_vertical_reverse_joint(event) - self.on_diagonal_joint(event) - self.on_vertical_reverse_joint(event) + def get_joint_coefficient(self, val: float, is_reverse=False): + if self.joint_pos_type_ctrl.GetStringSelection() == logger.transtext("繝懊シ繝ウ菴咲スョ"): + return val * (0.7 if is_reverse else 1.3) + return val def on_clear(self, event: wx.Event): self.simple_material_ctrl.SetStringSelection("") @@ -4680,8 +4818,8 @@ def on_clear(self, event: wx.Event): self.physics_type_ctrl.SetStringSelection(logger.transtext("蟶")) self.density_type_ctrl.SetStringSelection(logger.transtext("鬆らせ")) self.parent_type_ctrl.SetStringSelection(logger.transtext("荳ュ蠢")) - self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ髢")) - self.route_search_type_ctrl.SetStringSelection(logger.transtext("譬ケ蜈鬆らせ蜆ェ蜈")) + self.joint_pos_type_ctrl.SetStringSelection(logger.transtext("繝懊シ繝ウ菴咲スョ")) + self.route_search_type_ctrl.SetStringSelection(logger.transtext("蜑埼らせ蜆ェ蜈")) self.route_estimate_type_ctrl.SetStringSelection(logger.transtext("隗貞コヲ")) self.set_material_name(event) diff --git a/src/lnk.py b/src/lnk.py index fb3e916..1e5c16f 100644 --- a/src/lnk.py +++ b/src/lnk.py @@ -30,7 +30,7 @@ ), ( f"..\dist\{APP_NAME}_{VERSION_NAME}.exe - 繝繝舌ャ繧ー迚.lnk", - f'/c start "%cd%" "{APP_NAME}_{VERSION_NAME}.exe" --verbose 10 --out_log 0 --lang ja_JP', + f'/c start "%cd%" "{APP_NAME}_{VERSION_NAME}.exe" --verbose 10 --out_log 1 --lang ja_JP', f'"%SystemRoot%\System32\SHELL32.dll, 0"', ), ( diff --git a/src/locale/en_US/messages.json b/src/locale/en_US/messages.json index 8602078..347ebec 100644 --- a/src/locale/en_US/messages.json +++ b/src/locale/en_US/messages.json @@ -627,5 +627,70 @@ "縺薙l縺セ縺ァ謖螳壹&繧後◆陬セ蟇セ雎。鬆らせCSV繧貞肴欠螳壹〒縺阪∪縺吶": "You can respecify the tail target vertex CSV that has been specified so far.", "鬆らせシ壼ョ滄圀縺ョ鬆らせ縺ョ蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ェ縺暦シ噂n霍晞屬シ夐らせ縺ョ霍晞屬繧堤ュ蛾俣髫斐↓郢九>縺蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ゅjシ噂n荳ュ螟ョシ壹Γ繝繧キ繝・邵ヲ譁ケ蜷代ョ逵溘s荳ュ縺ョ縺ソ險育ョ怜ッセ雎。縺ィ縺吶k": "Vertices: calculate with actual vertex density (no vertex skip possibility)\nDistance: Calculate the distance of vertices with a density that connects them at equal intervals (possibility of skipping vertices)\nCenter: Only the center of the mesh in the vertical direction is subject to calculation", "荳ュ螟ョ": "center", - "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "Since the information necessary for generating the vertical joint could not be obtained, it will be skipped.\nWithout vertical joints, physics can stretch like cheese.\nCheck if there are any elements whose first row (root) is None in the vertex map.\nIf there is a None element at the root and the root CSV is not specified, specify the root CSV.縲Processing target: %s" + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "Since the information necessary for generating the vertical joint could not be obtained, it will be skipped.\nWithout vertical joints, physics can stretch like cheese.\nCheck if there are any elements whose first row (root) is None in the vertex map.\nIf there is a None element at the root and the root CSV is not specified, specify the root CSV.縲Processing target: %s", + "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳企Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲": "Processing is terminated because the top edge was not found for the physical direction.\nFor VRoid skirts, please check if the upper belt part is included.", + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶ゅ蜃ヲ逅蟇セ雎。: %s": "Since the information necessary for generating the vertical joint could not be obtained, it will be skipped.縲Processing target: %s", + "譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳喀n霆ク譁ケ蜷: 迚ゥ逅譁ケ蜷代ョ騾譁ケ蜷代r譬ケ蜈縺ィ縺励※謗ィ螳": "method for estimating root vertices\nAngle: Estimate root vertex similar to terminal vertex angle\nScale: Estimate the scale of the terminal vertex circumference and the root vertex circumference\nAxial: Estimated with the opposite direction of the physical direction as the root", + "霆ク譁ケ蜷": "axial direction", + "繧ェ繝輔そ繝繝": "offset", + "-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ": "-- -- [No.%s] Bone creation: %sth: Finished", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ蜀遨阪r蜆ェ蜈": "Techniques for traversing root vertices from terminal vertices\nPrior Vertex Prefer: Prefer orientation to estimated root vertex\nRoot vertex priority: Prioritize inner product with previous vertex", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n繧ケ繝ェ繝繝茨シ壹昴Μ蜑イ繧翫↓蛻繧檎岼縺後≠繧句エ蜷医↓繝。繝繧キ繝・襍ー譟サ縺梧仙粥縺励d縺吶>險ュ螳壹r蜈・繧後∪縺": "Shapes that require special treatment such as skirts\nAll Surfaces: Forcibly treats all surfaces as front surfaces (separate the thickness by back surface material) when the back surface detection misdetects a shape such as pleats (folded back on the poly split).\nSlit: Add settings that make it easier for mesh scanning to succeed when there is a break in the poly split.", + "繧ケ繝ェ繝繝": "slit", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n": "Shapes that require special treatment such as skirts\nAll Surfaces: Forcibly treats all surfaces as front surfaces (separate the thickness by back surface material) when the back surface detection misdetects shapes such as pleats (folded poly cracks).\n", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ隗貞コヲ蟾ョ繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈": "Techniques for traversing root vertices from terminal vertices\nPrioritize previous vertex: Prioritize angle difference with previous vertex\nRoot Vertex Prefer: Prefer the orientation to the inferred root vertex", + "-- %s: 莉ョ諠ウ髱「霑ス蜉: [%s, %s, %s]": "-- %s: add virtual face: [%s, %s, %s]", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼:邨ゆコ": "-- edge detection: %s: end", + "繧ィ繝繧ク縺梧、懷コ縺ァ縺阪↑縺九▲縺溘◆繧√∝ヲ逅繧剃クュ譁ュ縺励∪縺吶\n陬城擇縺ョ縺ゅk譚占ウェ縺ァ縲後☆縺ケ縺ヲ陦ィ髱「縲阪r驕ク謚槭@縺ヲ縺ェ縺縺九∫「コ隱阪@縺ヲ縺上□縺輔>縲": "Processing is aborted because an edge could not be detected.\nMake sure that you have not selected \"All Front\" for the material with back side.", + "-- 莉ョ諠ウ髱「遒コ隱: %s蛟狗岼:邨ゆコ": "-- Virtual face confirmation: %sth: end", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "-- edge detection: %sth(%s)", + "---- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "---- edge detection: %s th (%s)", + "-- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ": "-- parent bone check", + "-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ": "-- -- Parent bone check: %s th: end", + "-- 繝懊シ繝ウ驟咲スョ": "-- bone placement", + "-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ": "-- -- Bone Placement: %s:End", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「謚懊¢: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√昴Μ縺ョ荳ュ縺ォ髱「縺ョ遨コ縺縺溷エ謇縺後≠繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "Shapes that require special treatment such as skirts\nAll Surfaces: Forcibly treats all surfaces as front surfaces (separate the thickness by back surface material) when the back surface detection misdetects shapes such as pleats (folded poly cracks).\nSurface missing: If there is an empty surface in the poly by exporting to pmx with \"Remove transparent mesh\" (default ON) in VRoid Studio, put a virtual surface and set stable physics To do\n", + "髱「謚懊¢": "faceless", + "髱「謚懊¢縺ゅj": "There is an omission", + "繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧": "Bone Position: The joint enters the position of the bone\nBetween bones: Joints are inserted between bones", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「谺縺: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√お繝繧ク縺ァ縺ッ縺ェ縺上〒縺薙⊂縺薙@縺ヲ縺繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "Shapes that require special treatment such as skirts\nAll Surfaces: Forcibly treats all surfaces as front surfaces (separate the thickness by back surface material) when the back surface detection misdetects shapes such as pleats (folded poly cracks).\nMissing Faces: If there are irregularities instead of edges, such as outputting to pmx with \"Remove transparent mesh\" (default ON) in VRoid Studio, set a stable physics by pasting a virtual face.\n", + "髱「谺縺": "Face chip", + "蜷後§繧ク繝ァ繧、繝ウ繝亥錐縺梧里縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥ず繝ァ繧、繝ウ繝亥錐: %s": "A random number is added to the end because the same joint name has already been registered. Existing joint name: %s", + "蜷後§譚占ウェ繝サ蜷後§逡・遘ー縺ォ蟇セ縺励※隍謨ー縺ョ迚ゥ逅險ュ螳壹′蜑イ繧雁ス薙※繧峨l縺ヲ縺縺セ縺兔n逡ー縺ェ繧狗ョ謇縺ォ迚ゥ逅繧貞牡繧雁ス薙※縺溘>蝣エ蜷医∫払遘ー繧貞、峨∴縺ヲ縺繧九°遒コ隱阪@縺ヲ縺上□縺輔>縲": "Multiple physics settings are assigned to the same material and the same abbreviation\nIf you want to assign physics to different locations, make sure you change the abbreviations.", + "縲%s:%s縲題ク迚ゥ逅逕滓": "[%s:%s] chest physical generation", + "-- 閭ク迚ゥ逅: %s: 邨ゆコ": "-- chest physics: %s: end", + "隕ェ繝懊シ繝ウ繧定ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∽クュ蠢繝懊シ繝ウ縺ォ邏蝉サ倥¢縺セ縺: 隕ェ縲%s縲大ュ舌%s縲": "Since the parent bone could not be found, it will be linked to the center bone: Parent [%s] Child [%s]", + "蟶(繧ヲ繝シ繝ォ)": "cloth (wool)", + "譚占ウェ縺ョ譟斐i縺九&縲ょ央菴薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍募屓霆「蛻カ髯舌↓蠖ア髻ソ縺励∪縺吶\n蟆上&縺上↑繧九⊇縺ゥ繧医¥螟牙ス「縺励√☆縺舌↓蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ亥屓霆「蛻カ髯舌′螟ァ縺阪¥縲∵ク幄。ー縺碁ォ倥>シ": "softness of the material. Affects rigid body damping and joint movement/rotation limits.\nThe smaller it is, the better it deforms and quickly returns to its original shape. (Large rotation limit, high damping)", + "譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ繝舌ロ縺ョ蠑キ縺輔↓蠖ア髻ソ縺励∪縺吶\n螟ァ縺阪>縺サ縺ゥ螟牙ス「縺ョ謖ッ繧雁ケ縺悟、ァ縺阪¥縺ェ繧翫∪縺呻シ医≠繧薙∪繧雁、牙ス「縺励↑縺縺後∝、牙ス「縺吶k縺ィ縺阪ッ螟ァ縺阪¥螟牙ス「縺吶kシ": "The shape retention strength of a material. Affects the spring strength of the joint.\nThe larger the value, the greater the amplitude of deformation (not much deformation, but large deformation when deformed).", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement X of terminal longitudinal joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Y of terminal longitudinal joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal longitudinal joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement X of terminal longitudinal joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Y of terminal longitudinal joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal longitudinal joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Distal transverse joint travel X (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Y of terminal transverse joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal transverse joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Distal Transverse Joint Travel X (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Y of terminal transverse joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal transverse joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Distal Diagonal Joint Travel X (Minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement Y of end oblique joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement Z of terminal oblique joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Distal Diagonal Joint Travel X (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement Y of end oblique joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement Z of end oblique joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel X (minimum) of terminal longitudinal reverse joint\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Y of terminal longitudinal reverse joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal longitudinal reverse joint (minimum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel X (maximum) of terminal longitudinal reverse joint\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Displacement Y of terminal longitudinal reverse joint (maximum)\nAllowable amount of movement per mixel", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Travel Z of terminal longitudinal reverse joint (maximum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Lateral inverse joint travel X (minimum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Horizontal reverse joint movement Y (minimum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Translation Z of lateral reverse joint (minimum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Lateral reverse joint travel X (maximum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Horizontal reverse joint movement Y (maximum)\nAllowable amount of movement per mixel", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "Translation Z of lateral reverse joint (maximum)\nAllowable amount of movement per mixel" } \ No newline at end of file diff --git a/src/locale/ja_JP/messages.json b/src/locale/ja_JP/messages.json index 4867e0c..c8607d3 100644 --- a/src/locale/ja_JP/messages.json +++ b/src/locale/ja_JP/messages.json @@ -628,5 +628,69 @@ "縺薙l縺セ縺ァ謖螳壹&繧後◆陬セ蟇セ雎。鬆らせCSV繧貞肴欠螳壹〒縺阪∪縺吶": "縺薙l縺セ縺ァ謖螳壹&繧後◆陬セ蟇セ雎。鬆らせCSV繧貞肴欠螳壹〒縺阪∪縺吶", "鬆らせシ壼ョ滄圀縺ョ鬆らせ縺ョ蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ェ縺暦シ噂n霍晞屬シ夐らせ縺ョ霍晞屬繧堤ュ蛾俣髫斐↓郢九>縺蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ゅjシ噂n荳ュ螟ョシ壹Γ繝繧キ繝・邵ヲ譁ケ蜷代ョ逵溘s荳ュ縺ョ縺ソ險育ョ怜ッセ雎。縺ィ縺吶k": "鬆らせシ壼ョ滄圀縺ョ鬆らせ縺ョ蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ェ縺暦シ噂n霍晞屬シ夐らせ縺ョ霍晞屬繧堤ュ蛾俣髫斐↓郢九>縺蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ゅjシ噂n荳ュ螟ョシ壹Γ繝繧キ繝・邵ヲ譁ケ蜷代ョ逵溘s荳ュ縺ョ縺ソ險育ョ怜ッセ雎。縺ィ縺吶k", "荳ュ螟ョ": "荳ュ螟ョ", - "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s" + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s", + "譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳喀n霆ク譁ケ蜷: 迚ゥ逅譁ケ蜷代ョ騾譁ケ蜷代r譬ケ蜈縺ィ縺励※謗ィ螳": "譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳喀n霆ク譁ケ蜷: 迚ゥ逅譁ケ蜷代ョ騾譁ケ蜷代r譬ケ蜈縺ィ縺励※謗ィ螳", + "霆ク譁ケ蜷": "霆ク譁ケ蜷", + "繧ェ繝輔そ繝繝": "繧ェ繝輔そ繝繝", + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶ゅ蜃ヲ逅蟇セ雎。: %s": "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶ゅ蜃ヲ逅蟇セ雎。: %s", + "-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ": "-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ蜀遨阪r蜆ェ蜈": "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ蜀遨阪r蜆ェ蜈", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n繧ケ繝ェ繝繝茨シ壹昴Μ蜑イ繧翫↓蛻繧檎岼縺後≠繧句エ蜷医↓繝。繝繧キ繝・襍ー譟サ縺梧仙粥縺励d縺吶>險ュ螳壹r蜈・繧後∪縺": "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n繧ケ繝ェ繝繝茨シ壹昴Μ蜑イ繧翫↓蛻繧檎岼縺後≠繧句エ蜷医↓繝。繝繧キ繝・襍ー譟サ縺梧仙粥縺励d縺吶>險ュ螳壹r蜈・繧後∪縺", + "繧ケ繝ェ繝繝": "繧ケ繝ェ繝繝", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n": "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ隗貞コヲ蟾ョ繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈": "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ隗貞コヲ蟾ョ繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈", + "-- %s: 莉ョ諠ウ髱「霑ス蜉: [%s, %s, %s]": "-- %s: 莉ョ諠ウ髱「霑ス蜉: [%s, %s, %s]", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼:邨ゆコ": "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼:邨ゆコ", + "繧ィ繝繧ク縺梧、懷コ縺ァ縺阪↑縺九▲縺溘◆繧√∝ヲ逅繧剃クュ譁ュ縺励∪縺吶\n陬城擇縺ョ縺ゅk譚占ウェ縺ァ縲後☆縺ケ縺ヲ陦ィ髱「縲阪r驕ク謚槭@縺ヲ縺ェ縺縺九∫「コ隱阪@縺ヲ縺上□縺輔>縲": "繧ィ繝繧ク縺梧、懷コ縺ァ縺阪↑縺九▲縺溘◆繧√∝ヲ逅繧剃クュ譁ュ縺励∪縺吶\n陬城擇縺ョ縺ゅk譚占ウェ縺ァ縲後☆縺ケ縺ヲ陦ィ髱「縲阪r驕ク謚槭@縺ヲ縺ェ縺縺九∫「コ隱阪@縺ヲ縺上□縺輔>縲", + "-- 莉ョ諠ウ髱「遒コ隱: %s蛟狗岼:邨ゆコ": "-- 莉ョ諠ウ髱「遒コ隱: %s蛟狗岼:邨ゆコ", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)", + "---- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "---- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)", + "-- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ": "-- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ", + "-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ": "-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ", + "-- 繝懊シ繝ウ驟咲スョ": "-- 繝懊シ繝ウ驟咲スョ", + "-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ": "-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「謚懊¢: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√昴Μ縺ョ荳ュ縺ォ髱「縺ョ遨コ縺縺溷エ謇縺後≠繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「謚懊¢: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√昴Μ縺ョ荳ュ縺ォ髱「縺ョ遨コ縺縺溷エ謇縺後≠繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n", + "髱「謚懊¢": "髱「謚懊¢", + "髱「謚懊¢縺ゅj": "髱「謚懊¢縺ゅj", + "繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧": "繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「谺縺: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√お繝繧ク縺ァ縺ッ縺ェ縺上〒縺薙⊂縺薙@縺ヲ縺繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「谺縺: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√お繝繧ク縺ァ縺ッ縺ェ縺上〒縺薙⊂縺薙@縺ヲ縺繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n", + "髱「谺縺": "髱「谺縺", + "蜷後§繧ク繝ァ繧、繝ウ繝亥錐縺梧里縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥ず繝ァ繧、繝ウ繝亥錐: %s": "蜷後§繧ク繝ァ繧、繝ウ繝亥錐縺梧里縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥ず繝ァ繧、繝ウ繝亥錐: %s", + "蜷後§譚占ウェ繝サ蜷後§逡・遘ー縺ォ蟇セ縺励※隍謨ー縺ョ迚ゥ逅險ュ螳壹′蜑イ繧雁ス薙※繧峨l縺ヲ縺縺セ縺兔n逡ー縺ェ繧狗ョ謇縺ォ迚ゥ逅繧貞牡繧雁ス薙※縺溘>蝣エ蜷医∫払遘ー繧貞、峨∴縺ヲ縺繧九°遒コ隱阪@縺ヲ縺上□縺輔>縲": "蜷後§譚占ウェ繝サ蜷後§逡・遘ー縺ォ蟇セ縺励※隍謨ー縺ョ迚ゥ逅險ュ螳壹′蜑イ繧雁ス薙※繧峨l縺ヲ縺縺セ縺兔n逡ー縺ェ繧狗ョ謇縺ォ迚ゥ逅繧貞牡繧雁ス薙※縺溘>蝣エ蜷医∫払遘ー繧貞、峨∴縺ヲ縺繧九°遒コ隱阪@縺ヲ縺上□縺輔>縲", + "縲%s:%s縲題ク迚ゥ逅逕滓": "縲%s:%s縲題ク迚ゥ逅逕滓", + "-- 閭ク迚ゥ逅: %s: 邨ゆコ": "-- 閭ク迚ゥ逅: %s: 邨ゆコ", + "隕ェ繝懊シ繝ウ繧定ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∽クュ蠢繝懊シ繝ウ縺ォ邏蝉サ倥¢縺セ縺: 隕ェ縲%s縲大ュ舌%s縲": "隕ェ繝懊シ繝ウ繧定ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∽クュ蠢繝懊シ繝ウ縺ォ邏蝉サ倥¢縺セ縺: 隕ェ縲%s縲大ュ舌%s縲", + "蟶(繧ヲ繝シ繝ォ)": "蟶(繧ヲ繝シ繝ォ)", + "譚占ウェ縺ョ譟斐i縺九&縲ょ央菴薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍募屓霆「蛻カ髯舌↓蠖ア髻ソ縺励∪縺吶\n蟆上&縺上↑繧九⊇縺ゥ繧医¥螟牙ス「縺励√☆縺舌↓蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ亥屓霆「蛻カ髯舌′螟ァ縺阪¥縲∵ク幄。ー縺碁ォ倥>シ": "譚占ウェ縺ョ譟斐i縺九&縲ょ央菴薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍募屓霆「蛻カ髯舌↓蠖ア髻ソ縺励∪縺吶\n蟆上&縺上↑繧九⊇縺ゥ繧医¥螟牙ス「縺励√☆縺舌↓蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ亥屓霆「蛻カ髯舌′螟ァ縺阪¥縲∵ク幄。ー縺碁ォ倥>シ", + "譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ繝舌ロ縺ョ蠑キ縺輔↓蠖ア髻ソ縺励∪縺吶\n螟ァ縺阪>縺サ縺ゥ螟牙ス「縺ョ謖ッ繧雁ケ縺悟、ァ縺阪¥縺ェ繧翫∪縺呻シ医≠繧薙∪繧雁、牙ス「縺励↑縺縺後∝、牙ス「縺吶k縺ィ縺阪ッ螟ァ縺阪¥螟牙ス「縺吶kシ": "譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ繝舌ロ縺ョ蠑キ縺輔↓蠖ア髻ソ縺励∪縺吶\n螟ァ縺阪>縺サ縺ゥ螟牙ス「縺ョ謖ッ繧雁ケ縺悟、ァ縺阪¥縺ェ繧翫∪縺呻シ医≠繧薙∪繧雁、牙ス「縺励↑縺縺後∝、牙ス「縺吶k縺ィ縺阪ッ螟ァ縺阪¥螟牙ス「縺吶kシ", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮" } \ No newline at end of file diff --git a/src/locale/zh_CN/messages.json b/src/locale/zh_CN/messages.json index dc77367..136d199 100644 --- a/src/locale/zh_CN/messages.json +++ b/src/locale/zh_CN/messages.json @@ -628,5 +628,70 @@ "縺薙l縺セ縺ァ謖螳壹&繧後◆陬セ蟇セ雎。鬆らせCSV繧貞肴欠螳壹〒縺阪∪縺吶": "謔ィ蜿ッ莉・驥肴眠謖螳壼芦逶ョ蜑堺クコ豁「蟾イ謖螳夂噪蟆セ驛ィ逶ョ譬鬘カ轤ケ CSV縲", "鬆らせシ壼ョ滄圀縺ョ鬆らせ縺ョ蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ェ縺暦シ噂n霍晞屬シ夐らせ縺ョ霍晞屬繧堤ュ蛾俣髫斐↓郢九>縺蟇蠎ヲ縺ァ險育ョ励☆繧具シ磯らせ繧ケ繧ュ繝繝怜庄閭ス諤ァ縺ゅjシ噂n荳ュ螟ョシ壹Γ繝繧キ繝・邵ヲ譁ケ蜷代ョ逵溘s荳ュ縺ョ縺ソ險育ョ怜ッセ雎。縺ィ縺吶k": "鬘カ轤ケシ壻スソ逕ィ螳樣刔鬘カ轤ケ蟇蠎ヲ隶。邂暦シ域イ。譛蛾。カ轤ケ霍ウ霑逧蜿ッ閭ス諤ァシ噂n霍晉ヲサシ夊ョ。邂鈴。カ轤ケ逧霍晉ヲサシ悟カ蟇蠎ヲ莉・逶ク遲臥噪髣エ髫碑ソ樊磁螳莉ャシ郁キウ霑鬘カ轤ケ逧蜿ッ閭ス諤ァシ噂n荳ュ蠢シ壼宵隶。邂怜桙逶エ譁ケ蜷醍噪鄂第シ荳ュ蠢", "荳ュ螟ョ": "荳ュ螟ョ", - "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "逕ア莠取裏豕戊執蠕礼函謌仙桙逶エ蜈ウ闃よ園髴逧菫。諱ッシ悟屏豁、蟆霍ウ霑隸・菫。諱ッ縲\n豐。譛牙桙逶エ蜈ウ闃ゑシ檎黄逅蟄ヲ蜿ッ莉・蜒丞・カ驟ェ荳譬キ莨ク螻輔\n譽譟・鬘カ轤ケ譏蟆荳ュ譏ッ蜷ヲ譛臥ャャ荳陦鯉シ域ケシ我クコ None 逧蜈邏縲\n螯よ棡譬ケ荳ュ譛 None 蜈邏蟷カ荳疲悴謖螳壽ケ CSVシ瑚ッキ謖螳壽ケ CSV縲ょ、逅逶ョ譬シ%s" + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\nNone縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s": "逕ア莠取裏豕戊執蠕礼函謌仙桙逶エ蜈ウ闃よ園髴逧菫。諱ッシ悟屏豁、蟆霍ウ霑隸・菫。諱ッ縲\n豐。譛牙桙逶エ蜈ウ闃ゑシ檎黄逅蟄ヲ蜿ッ莉・蜒丞・カ驟ェ荳譬キ莨ク螻輔\n譽譟・鬘カ轤ケ譏蟆荳ュ譏ッ蜷ヲ譛臥ャャ荳陦鯉シ域ケシ我クコ None 逧蜈邏縲\n螯よ棡譬ケ荳ュ譛 None 蜈邏蟷カ荳疲悴謖螳壽ケ CSVシ瑚ッキ謖螳壽ケ CSV縲ょ、逅逶ョ譬シ%s", + "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳企Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲": "逕ア莠取悴謇セ蛻ー迚ゥ逅譁ケ蜷醍噪鬘カ驛ィ霎ケ郛假シ悟屏豁、螟逅扈域ュ「縲\n蟇ケ莠 VRoid 陬吝ュ撰シ瑚ッキ譽譟・譏ッ蜷ヲ蛹諡ャ荳企Κ閻ー蟶ヲ驛ィ蛻縲", + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶ゅ蜃ヲ逅蟇セ雎。: %s": "逕ア莠取裏豕戊執蠕礼函謌仙桙逶エ謗・螟エ謇髴逧菫。諱ッシ悟屏豁、蟆霍ウ霑縲 窶門、逅逶ョ譬シ%s", + "譬ケ蜈鬆らせ繧呈耳螳壹☆繧矩圀縺ョ謇区ウ表n隗貞コヲ: 譛ォ遶ッ鬆らせ隗貞コヲ縺ォ鬘樔シシ縺励◆譬ケ蜈鬆らせ繧呈耳螳喀n邵ョ蟆コ: 譛ォ遶ッ鬆らせ蜀蜻ィ縺ィ譬ケ蜈鬆らせ蜀蜻ィ縺ョ邵ョ蟆コ繧呈耳螳喀n霆ク譁ケ蜷: 迚ゥ逅譁ケ蜷代ョ騾譁ケ蜷代r譬ケ蜈縺ィ縺励※謗ィ螳": "莨ー隶。譬ケ鬘カ轤ケ逧譁ケ豕表nAngleシ壻シー隶。譬ケ鬘カ轤ケ邀サ莨シ莠守サ育ォッ鬘カ轤ケ隗貞コヲ\nscaleシ壻シー隶。扈育ォッ鬘カ轤ケ蜻ィ髟ソ蜥梧ケ鬘カ轤ケ蜻ィ髟ソ逧豈比セ欺nAxialシ壻サ・迚ゥ逅譁ケ蜷醍噪蜿肴婿蜷台クコ譬ケ莨ー隶。", + "霆ク譁ケ蜷": "霓エ蜷", + "繧ェ繝輔そ繝繝": "謚オ豸", + "-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ": "-- -- [No.%s] 鬪ィ鬪シ蛻帛サコシ%sthシ壼キイ螳梧", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ蜀遨阪r蜆ェ蜈": "莉守サ育ォッ鬘カ轤ケ驕榊紙譬ケ鬘カ轤ケ逧謚蟾ァ\nPrior Vertex Preferシ壻シ伜井コ惹シー隶。逧譬ケ鬘カ轤ケ逧譁ケ蜷曾n譬ケ鬘カ轤ケ莨伜育コァシ壻シ伜郁陌台ク主燕荳荳ェ鬘カ轤ケ逧蜀遘ッ", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n繧ケ繝ェ繝繝茨シ壹昴Μ蜑イ繧翫↓蛻繧檎岼縺後≠繧句エ蜷医↓繝。繝繧キ繝・襍ー譟サ縺梧仙粥縺励d縺吶>險ュ螳壹r蜈・繧後∪縺": "髴隕∫音谿雁、逅逧蠖「迥カシ御セ句ヲり」吝ュ申nAll Surfacesシ壼ス楢レ髱「譽豬玖ッッ譽豬句芦隍カ逧ア遲牙ス「迥カシ亥惠poly split荳雁髄蜷取釜蜿シ画慮シ悟シコ蛻カ蟆謇譛芽。ィ髱「隗荳コ豁」髱「シ磯夊ソ閭碁擇譚先侭蛻遖サ蜴壼コヲシ峨\n迢ュ郛晢シ壽キサ蜉隶セ鄂ョシ御スソ鄂第シ謇ォ謠丞惠螟夊セケ蠖「諡蛻荳ュ譁ュ譌カ譖エ螳ケ譏捺仙粥縲", + "繧ケ繝ェ繝繝": "迢ュ郛", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n": "髴隕∫音谿雁、逅逧蠖「迥カシ御セ句ヲり」吝ュ申nAll Surfacesシ壼ス楢レ髱「譽豬玖ッッ譽豬玖、カ逧アシ域釜蜿閨夊」らコケシ臥ュ牙ス「迥カ譌カシ悟シコ蛻カ蟆謇譛芽。ィ髱「隗荳コ豁」髱「シ磯夊ソ閭碁擇譚先侭蛻遖サ蜴壼コヲシ峨\n", + "譛ォ遶ッ鬆らせ縺九i譬ケ蜈鬆らせ繧定オー譟サ縺吶k髫帙ョ謇区ウ表n蜑埼らせ蜆ェ蜈: 蜑埼らせ縺ィ縺ョ隗貞コヲ蟾ョ繧貞━蜈\n譬ケ蜈鬆らせ蜆ェ蜈: 謗ィ螳壽ケ蜈鬆らせ縺ク縺ョ蜷代″繧貞━蜈": "莉守サ育ォッ鬘カ轤ケ驕榊紙譬ケ鬘カ轤ケ逧謚蟾ァ\nPrioritize previous vertexシ壻シ伜郁陌台ク主燕荳荳ェ鬘カ轤ケ逧隗貞コヲ蟾ョ\nRoot Vertex Preferシ壻シ伜井コ取耳譁ュ逧譬ケ鬘カ轤ケ逧譁ケ蜷", + "-- %s: 莉ョ諠ウ髱「霑ス蜉: [%s, %s, %s]": "-- %s: 豺サ蜉陌壽供髱「蟄: [%s, %s, %s]", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼:邨ゆコ": "-- 霎ケ郛俶」豬具シ%sシ夂サ捺據", + "繧ィ繝繧ク縺梧、懷コ縺ァ縺阪↑縺九▲縺溘◆繧√∝ヲ逅繧剃クュ譁ュ縺励∪縺吶\n陬城擇縺ョ縺ゅk譚占ウェ縺ァ縲後☆縺ケ縺ヲ陦ィ髱「縲阪r驕ク謚槭@縺ヲ縺ェ縺縺九∫「コ隱阪@縺ヲ縺上□縺輔>縲": "逕ア莠取裏豕墓」豬句芦霎ケ郛假シ悟、逅荳ュ豁「縲\n遑ョ菫晄お豐。譛我クコ蟶ヲ閭碁擇逧譚先侭騾画叫窶懷ィ豁」髱「窶昴", + "-- 莉ョ諠ウ髱「遒コ隱: %s蛟狗岼:邨ゆコ": "-- 陌壽供莠コ閼ク遑ョ隶、シ%sthシ夂サ捺據", + "-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "-- 霎ケ郛俶」豬具シ%sth(%s)", + "---- 繧ィ繝繧ク讀懷コ: %s蛟狗岼(%s)": "----霎ケ郛俶」豬具シ%s谺。シ%sシ", + "-- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ": "-- 辷カ鬪ィ鬪シ譽譟・", + "-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ": "-- -- 辷カ鬪ィ鬪シ譽譟・シ%s 谺。シ夂サ捺據", + "-- 繝懊シ繝ウ驟咲スョ": "-- 鬪ィ鬪シ謾セ鄂ョ", + "-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ": "-- -- 鬪ィ鬪シ謾セ鄂ョシ%sthシ夂サ捺據", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「謚懊¢: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√昴Μ縺ョ荳ュ縺ォ髱「縺ョ遨コ縺縺溷エ謇縺後≠繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "髴隕∫音谿雁、逅逧蠖「迥カシ御セ句ヲり」吝ュ申nAll Surfacesシ壼ス楢レ髱「譽豬玖ッッ譽豬玖、カ逧アシ域釜蜿閨夊」らコケシ臥ュ牙ス「迥カ譌カシ悟シコ蛻カ蟆謇譛芽。ィ髱「隗荳コ豁」髱「シ磯夊ソ閭碁擇譚先侭蛻遖サ蜴壼コヲシ峨\nSurface missingシ壼ヲよ棡蝨ィVRoid Studio荳ュ菴ソ逕ィ窶彝emove transparent mesh窶晢シ磯サ倩ョ、蠑蜷ッシ牙ッシ蜃コ蛻ーpmxシ継oly荳ュ譛我ク荳ェ遨コ逧陦ィ髱「シ梧叛鄂ョ荳荳ェ陌壽供陦ィ髱「蟷カ隶セ鄂ョ遞ウ螳夂噪迚ゥ逅蛛喀n", + "髱「謚懊¢": "譌閼ク", + "髱「謚懊¢縺ゅj": "譛蛾@貍", + "繝懊シ繝ウ菴咲スョ: 繝懊シ繝ウ縺ョ菴咲スョ縺ォ繧ク繝ァ繧、繝ウ繝医′蜈・繧欺n繝懊シ繝ウ髢: 繝懊シ繝ウ縺ィ繝懊シ繝ウ縺ョ髢薙↓繧ク繝ァ繧、繝ウ繝医′蜈・繧": "鬪ィ鬪シ菴咲スョシ壼ウ闃りソ帛・鬪ィ鬪シ逧菴咲スョ\nBetween bonesシ壼ウ闃よ薯蜈・鬪ィ鬪シ荵矩龍", + "繧ケ繧ォ繝シ繝育ュ峨〒迚ケ谿翫↑蜃ヲ逅縺悟ソ隕√↑蠖「迥カ\n蜈ィ縺ヲ陦ィ髱「: 繝励Μ繝シ繝シ医昴Μ蜑イ縺ォ謚倥j霑斐@縺後≠繧具シ峨↑縺ゥ縺ョ蠖「迥カ縺ァ陬城擇蛻、螳壹′隱、讀懃衍繧偵☆繧句エ蜷医∝シキ蛻カ逧縺ォ蜈ィ縺ヲ縺ョ髱「繧定。ィ髱「縺ィ縺励※謇ア縺縺セ縺呻シ亥字縺ソ縺ッ陬城擇譚占ウェ縺ォ蛻縺代※縺上□縺輔>シ噂n髱「谺縺: VRoid Studio縺ァ縲碁乗弱Γ繝繧キ繝・縺ョ蜑企勁縲搾シ医ョ繝輔か繝ォ繝ONシ峨ョ迥カ諷九〒pmx縺ォ蜃コ蜉帙☆繧九↑縺ゥ縺励※縲√お繝繧ク縺ァ縺ッ縺ェ縺上〒縺薙⊂縺薙@縺ヲ縺繧句エ蜷医∽サョ諠ウ髱「繧定イシ縺」縺ヲ螳牙ョ壹@縺溽黄逅繧定ィュ螳壹@縺セ縺兔n": "髴隕∫音谿雁、逅逧蠖「迥カシ御セ句ヲり」吝ュ申nAll Surfacesシ壼ス楢レ髱「譽豬玖ッッ譽豬玖、カ逧アシ域釜蜿閨夊」らコケシ臥ュ牙ス「迥カ譌カシ悟シコ蛻カ蟆謇譛芽。ィ髱「隗荳コ豁」髱「シ磯夊ソ閭碁擇譚先侭蛻遖サ蜴壼コヲシ峨\nMissing Facesシ壼ヲよ棡譛我ク崎ァ蛻呵御ク肴弍霎ケ郛假シ御セ句ヲょ惠 VRoid Studio 荳ュ菴ソ逕ィ窶彝emove transparent mesh窶晢シ磯サ倩ョ、 ONシ芽セ灘コ蛻ー pmxシ碁夊ソ邊倩エエ陌壽供髱「譚・隶セ鄂ョ遞ウ螳夂噪迚ゥ逅縲\n", + "髱「谺縺": "莠コ閼ク闃ッ迚", + "蜷後§繧ク繝ァ繧、繝ウ繝亥錐縺梧里縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥ず繝ァ繧、繝ウ繝亥錐: %s": "逕ア莠主キイ扈乗ウィ蜀御コ逶ク蜷檎噪閨泌錐シ梧園莉・蝨ィ譛ォ蟆セ豺サ蜉荳荳ェ髫乗惻謨ー縲ら鴫譛芽#蜷搾シ%s", + "蜷後§譚占ウェ繝サ蜷後§逡・遘ー縺ォ蟇セ縺励※隍謨ー縺ョ迚ゥ逅險ュ螳壹′蜑イ繧雁ス薙※繧峨l縺ヲ縺縺セ縺兔n逡ー縺ェ繧狗ョ謇縺ォ迚ゥ逅繧貞牡繧雁ス薙※縺溘>蝣エ蜷医∫払遘ー繧貞、峨∴縺ヲ縺繧九°遒コ隱阪@縺ヲ縺上□縺輔>縲": "螟壻クェ迚ゥ逅隶セ鄂ョ蛻驟咲サ咏嶌蜷檎噪譚先侭蜥檎嶌蜷檎噪郛ゥ蜀兔n螯よ棡謔ィ諠ウ蟆迚ゥ逅蛻驟咲サ吩ク榊酔逧菴咲スョシ瑚ッキ遑ョ菫晄峩謾ケ郛ゥ蜀吶", + "縲%s:%s縲題ク迚ゥ逅逕滓": "[%s:%s]螳晉ョア迚ゥ逅逕滓", + "-- 閭ク迚ゥ逅: %s: 邨ゆコ": "-- 閭ク驛ィ迚ゥ逅シ%sシ夂サ捺據", + "隕ェ繝懊シ繝ウ繧定ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∽クュ蠢繝懊シ繝ウ縺ォ邏蝉サ倥¢縺セ縺: 隕ェ縲%s縲大ュ舌%s縲": "逕ア莠取伽荳榊芦辷カ鬪ィ鬪シシ悟ョ蟆體セ謗・蛻ー荳ュ蠢鬪ィ鬪シシ啀arent [%s] Child [%s]", + "蟶(繧ヲ繝シ繝ォ)": "蟶シ育セ頑ッ幢シ", + "譚占ウェ縺ョ譟斐i縺九&縲ょ央菴薙ョ貂幄。ー繝サ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍募屓霆「蛻カ髯舌↓蠖ア髻ソ縺励∪縺吶\n蟆上&縺上↑繧九⊇縺ゥ繧医¥螟牙ス「縺励√☆縺舌↓蜈縺ョ蠖「迥カ縺ォ謌サ繧翫∪縺吶ゑシ亥屓霆「蛻カ髯舌′螟ァ縺阪¥縲∵ク幄。ー縺碁ォ倥>シ": "譚先侭逧譟碑スッ蠎ヲ縲ょスア蜩榊壻ス馴仆蟆シ蜥悟ウ闃りソ仙勘/譌玖スャ髯仙宛縲\n螳雜雁ー擾シ悟序蠖「雜雁・ス蟷カ霑騾滓△螟榊芦蜴滓擂逧蠖「迥カ縲 シ亥、ァ蝗櫁スャ髯蝉ス搾シ碁ォ倬仆蟆シシ", + "譚占ウェ縺ョ蠖「迥カ邯ュ謖∝シキ蠎ヲ縲ゅず繝ァ繧、繝ウ繝医ョ繝舌ロ縺ョ蠑キ縺輔↓蠖ア髻ソ縺励∪縺吶\n螟ァ縺阪>縺サ縺ゥ螟牙ス「縺ョ謖ッ繧雁ケ縺悟、ァ縺阪¥縺ェ繧翫∪縺呻シ医≠繧薙∪繧雁、牙ス「縺励↑縺縺後∝、牙ス「縺吶k縺ィ縺阪ッ螟ァ縺阪¥螟牙ス「縺吶kシ": "譚先侭逧蠖「迥カ菫晄戟蠑コ蠎ヲ縲ょスア蜩榊ウ闃ら噪蠑ケ邁ァ蠑コ蠎ヲ縲\n蛟シ雜雁、ァシ悟序蠖「蟷蠎ヲ雜雁、ァシ亥序蠖「荳榊、夲シ悟序蠖「譌カ蜿伜ス「螟ァシ峨", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エ菴咲ァサXシ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エY陦檎ィ具シ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エ陦檎ィ技シ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エ菴咲ァサXシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エ陦檎ィ戯シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷第磁螟エ陦檎ィ技シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "霑懃ォッ讓ェ蜷大ウ闃り。檎ィ Xシ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ蜷第磁螟エY陦檎ィ具シ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ蜷第磁螟エ陦檎ィ Zシ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "霑懃ォッ讓ェ蜷大ウ闃り。檎ィ Xシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ蜷第磁螟エY陦檎ィ具シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ讓ェ蜷第磁螟エ陦檎ィ技シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "霑懃ォッ蟇ケ隗貞ウ闃り。檎ィ Xシ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懈磁螟エ菴咲ァサYシ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ譁懈磁螟エ菴咲ァサZシ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "霑懃ォッ蟇ケ隗貞ウ闃り。檎ィ Xシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "遶ッ譁懈磁螟エ菴咲ァサYシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ譁懊a繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "遶ッ譁懈磁螟エZ陦檎ィ具シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜿肴磁螟エ陦檎ィ宜シ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷大渚蜷第磁螟エ陦檎ィ戯シ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷大渚蜷第磁螟エ陦檎ィ技シ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜿肴磁螟エ陦檎ィ宜シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜿肴磁螟エ菴咲ァサYシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "譛ォ遶ッ邵ヲ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "譛ォ遶ッ郤オ蜷大渚蜷第磁螟エ陦檎ィ技シ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ蜷大渚蜷大ウ闃り。檎ィ Xシ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "豌エ蟷ウ蜿榊髄蜈ウ闃りソ仙勘 Yシ域怙蟆擾シ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛蟆)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ蜷大渚蜷第磁螟エ蟷ウ遘サ Zシ域怙蟆丞シシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍氷(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ蜷大渚蜷大ウ闃り。檎ィ Xシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍漂(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "豌エ蟷ウ蜿榊髄蜈ウ闃りソ仙勘 Yシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥", + "讓ェ騾繧ク繝ァ繧、繝ウ繝医ョ遘サ蜍瓢(譛螟ァ)\n1繝溘け繧サ繝ォ縺ゅ◆繧翫ョ險ア螳ケ遘サ蜍暮": "讓ェ蜷大渚蜷第磁螟エ蟷ウ遘サ Zシ域怙螟ァシ噂n豈丈クェ豺キ蜷亥勣逧蜈∬ョク遘サ蜉ィ驥" } \ No newline at end of file diff --git a/src/module/MMath.pxd b/src/module/MMath.pxd index dabfe5d..d336211 100644 --- a/src/module/MMath.pxd +++ b/src/module/MMath.pxd @@ -283,6 +283,8 @@ cdef class MQuaternion: cpdef MVector3D toEulerAngles(self) + cpdef MVector3D separateEulerAngles(self) + cpdef double toDegree(self) cpdef double toDegreeSign(self, MVector3D local_axis) diff --git a/src/module/MMath.pyx b/src/module/MMath.pyx index 0dbec0d..83adc75 100644 --- a/src/module/MMath.pyx +++ b/src/module/MMath.pyx @@ -296,7 +296,7 @@ cdef class MVector2D: class MPoint: - def __init__(self, p=MVector3D()): + def __init__(self, p: MVector3D): self.point = p def get_point(self, f: float): @@ -305,28 +305,38 @@ class MPoint: class MLine: - def __init__(self, p=MPoint(), v=MVector3D()): + def __init__(self, p: MPoint, v: MVector3D): self.point = p self.vector_start = v + self.vector_real = p.point - v + self.vector = (p.point - v).normalized() + + def get_point(self, f: float): + return self.vector_start + (self.vector_real * f) class MSegment(MLine): - def __init__(self, p=MPoint(), sv=MVector3D(), ev=MVector3D()): - super().__init__(p, sv) + def __init__(self, sv: MVector3D, ev: MVector3D): + super().__init__(MPoint((sv + ev) / 2), sv) self.vector_end = ev + self.vector_real = ev - sv + self.vector = self.vector_real.normalized() + + def get_point(self, f: float): + return self.vector_start + (self.vector_real * f) class MSphere: - def __init__(self, p=MPoint(), r=1.0): + def __init__(self, p: MPoint, r=1.0): self.point = p self.radius = r class MCapsule: - def __init__(self, s=MSegment(), r=0.0): + def __init__(self, s: MSegment, r=0.0): self.segment = s self.radius = r @@ -1064,6 +1074,18 @@ cdef class MQuaternion: return MVector3D(euler.x(), -euler.y(), -euler.z()) + cpdef MVector3D separateEulerAngles(self): + # ZXY縺ョ蝗櫁サ「鬆蠎上〒繧ェ繧、繝ゥ繝シ隗貞コヲ繧貞蜑イ縺吶k + # https://programming-surgeon.com/script/euler-python-script/ + cdef MMatrix4x4 mat = self.normalized().toMatrix4x4() + cdef np.ndarray[DTYPE_FLOAT_t, ndim=2] m = mat.data() + + cdef float z_radian = atan2(-m[0, 1], m[0, 0]) + cdef float x_radian = atan2(m[2, 1] * cos(z_radian), m[1, 1]) + cdef float y_radian = atan2(-m[2, 0], m[2, 2]) + + return MVector3D(degrees(x_radian), degrees(y_radian), degrees(z_radian)) + # http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q37 cpdef MVector3D toEulerAngles(self): cdef DTYPE_FLOAT_t xp = self.data().x diff --git a/src/service/PmxTailorExportService.py b/src/service/PmxTailorExportService.py index 640e009..1e3f0ef 100644 --- a/src/service/PmxTailorExportService.py +++ b/src/service/PmxTailorExportService.py @@ -4,13 +4,14 @@ import os import traceback import numpy as np -import itertools import math import copy import bezier import csv import random import string +from itertools import combinations +from collections import Counter from glob import glob from module.MOptions import MExportOptions @@ -498,6 +499,14 @@ def clear_physics(self, model: PmxModel, is_overwrite: bool): logger.info("鬆らせ蜀崎ィュ螳") + if param_option["parent_bone_name"] not in model.bones: + logger.warning( + "謖螳壹&繧後◆蜷榊燕縺ョ隕ェ繝懊シ繝ウ縺悟ュ伜惠縺励↑縺縺溘a縲∫黄逅繧ッ繝ェ繧「蜃ヲ逅繧剃クュ譁ュ縺励∪縺 隕ェ繝懊シ繝ウ: %s", + param_option["parent_bone_name"], + decoration=MLogger.DECORATION_BOX, + ) + return model + parent_bone = model.bones[param_option["parent_bone_name"]] for n, vertex in enumerate(model.vertex_dict.values()): @@ -731,9 +740,177 @@ def create_physics(self, model: PmxModel, param_option: dict): model.comment += f"\r\n縲縲{logger.transtext('逡・遘ー')}: {param_option['abb_name']}" model.comment += f", {logger.transtext('蜑帑ス薙げ繝ォ繝シ繝')}: {param_option['rigidbody'].collision_group + 1}" # model.comment += f", {logger.transtext('邏ー縺九&')}: {param_option['fineness']}" - model.comment += f", {logger.transtext('雉ェ驥')}: {param_option['mass']}" - model.comment += f", {logger.transtext('譟斐i縺九&')}: {param_option['air_resistance']}" - model.comment += f", {logger.transtext('蠑オ繧')}: {param_option['shape_maintenance']}" + model.comment += f", {logger.transtext('雉ェ驥')}: {round(param_option['mass'], 3)}" + model.comment += f", {logger.transtext('譟斐i縺九&')}: {round(param_option['air_resistance'], 3)}" + model.comment += f", {logger.transtext('蠑オ繧')}: {round(param_option['shape_maintenance'], 3)}" + model.comment += f", {logger.transtext('迚ケ谿雁ス「迥カ')}: {param_option['special_shape']}" + model.comment += f"\r\n縲縲{logger.transtext('繝懊シ繝ウ蟇蠎ヲ')}" + model.comment += f", {logger.transtext('邵ヲ蟇蠎ヲ')}: {param_option['vertical_bone_density']}" + model.comment += f", {logger.transtext('讓ェ蟇蠎ヲ')}: {param_option['horizonal_bone_density']}" + model.comment += f", {logger.transtext('繧ェ繝輔そ繝繝')}: {param_option['horizonal_bone_offset']}" + model.comment += f", {logger.transtext('蟇蠎ヲ蝓コ貅')}: {param_option['density_type']}" + model.comment += f"\r\n縲縲{logger.transtext('譬ケ蜈蜑帑ス')}" + model.comment += f", {logger.transtext('雉ェ驥')}: {round(param_option['rigidbody'].param.mass, 3)}" + model.comment += f", {logger.transtext('遘サ蜍墓ク幄。ー')}: {round(param_option['rigidbody'].param.linear_damping, 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「貂幄。ー')}: {round(param_option['rigidbody'].param.angular_damping, 3)}" + model.comment += f", {logger.transtext('蜿咲匱蜉')}: {round(param_option['rigidbody'].param.restitution, 3)}" + model.comment += f", {logger.transtext('鞫ゥ謫ヲ蜉')}: {round(param_option['rigidbody'].param.friction, 3)}" + model.comment += f", {logger.transtext('菫よ焚')}: {round(param_option['rigidbody_coefficient'], 3)}" + model.comment += f"\r\n縲縲{logger.transtext('蜑帑ス薙ョ蜴壹∩')}" + model.comment += f", {logger.transtext('譬ケ蜈蜴壹∩')}: {round(param_option['rigidbody_root_thicks'], 3)}" + model.comment += f", {logger.transtext('譛ォ遶ッ蜴壹∩')}: {round(param_option['rigidbody_end_thicks'], 3)}" + model.comment += f"\r\n縲縲{logger.transtext('隧ウ邏ー繧ェ繝励す繝ァ繝ウ')}" + model.comment += f", {logger.transtext('迚ゥ逅謗・邯')}: {param_option['parent_type']}" + model.comment += f", {logger.transtext('迚ゥ逅繧ソ繧、繝')}: {param_option['physics_type']}" + model.comment += f", {logger.transtext('繧ク繝ァ繧、繝ウ繝井ス咲スョ')}: {param_option['joint_pos_type']}" + model.comment += f", {logger.transtext('繝ォ繝シ繝域爾邏「')}: {param_option['route_search_type']}" + model.comment += f", {logger.transtext('譬ケ蜈鬆らせ謗ィ螳')}: {param_option['route_estimate_type']}" + model.comment += f", {logger.transtext('迚ゥ逅隕ェ')}: {param_option['physics_parent']}" + + if param_option["vertical_joint"]: + model.comment += f"\r\n縲縲{logger.transtext('邵ヲ繧ク繝ァ繧、繝ウ繝')}" + model.comment += f", {logger.transtext('蛻カ髯蝉ソよ焚')}: {round(param_option['vertical_joint_coefficient'], 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('遘サ蜍氷(譛蟆)')}: {round(param_option['vertical_joint'].translation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛蟆)')}: {round(param_option['vertical_joint'].translation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛蟆)')}: {round(param_option['vertical_joint'].translation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍氷(譛螟ァ)')}: {round(param_option['vertical_joint'].translation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛螟ァ)')}: {round(param_option['vertical_joint'].translation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛螟ァ)')}: {round(param_option['vertical_joint'].translation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('蝗櫁サ「X(譛蟆)')}: {round(param_option['vertical_joint'].rotation_limit_min.x(), 3)}" + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛蟆)')}: {round(param_option['vertical_joint'].rotation_limit_min.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛蟆)')}: {round(param_option['vertical_joint'].rotation_limit_min.z(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「X(譛螟ァ)')}: {round(param_option['vertical_joint'].rotation_limit_max.x(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛螟ァ)')}: {round(param_option['vertical_joint'].rotation_limit_max.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛螟ァ)')}: {round(param_option['vertical_joint'].rotation_limit_max.z(), 3)}" + ) + model.comment += f"\r\n縲縲縲縲{logger.transtext('縺ー縺ュ(遘サ蜍氷)')}: {round(param_option['vertical_joint'].spring_constant_translation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍漂)')}: {round(param_option['vertical_joint'].spring_constant_translation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍瓢)')}: {round(param_option['vertical_joint'].spring_constant_translation.z(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「X)')}: {round(param_option['vertical_joint'].spring_constant_rotation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Y)')}: {round(param_option['vertical_joint'].spring_constant_rotation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Z)')}: {round(param_option['vertical_joint'].spring_constant_rotation.z(), 3)}" + + if param_option["horizonal_joint"]: + model.comment += f"\r\n縲縲{logger.transtext('讓ェ繧ク繝ァ繧、繝ウ繝')}" + model.comment += f", {logger.transtext('蛻カ髯蝉ソよ焚')}: {param_option['horizonal_joint_coefficient']}" + model.comment += f", {logger.transtext('隕ェ蜑帑ス楢キ晞屬蛻カ髯')}: {param_option['horizonal_joint_restruct']}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('遘サ蜍氷(譛蟆)')}: {round(param_option['horizonal_joint'].translation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛蟆)')}: {round(param_option['horizonal_joint'].translation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛蟆)')}: {round(param_option['horizonal_joint'].translation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍氷(譛螟ァ)')}: {round(param_option['horizonal_joint'].translation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛螟ァ)')}: {round(param_option['horizonal_joint'].translation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛螟ァ)')}: {round(param_option['horizonal_joint'].translation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('蝗櫁サ「X(譛蟆)')}: {round(param_option['horizonal_joint'].rotation_limit_min.x(), 3)}" + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛蟆)')}: {round(param_option['horizonal_joint'].rotation_limit_min.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛蟆)')}: {round(param_option['horizonal_joint'].rotation_limit_min.z(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「X(譛螟ァ)')}: {round(param_option['horizonal_joint'].rotation_limit_max.x(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛螟ァ)')}: {round(param_option['horizonal_joint'].rotation_limit_max.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛螟ァ)')}: {round(param_option['horizonal_joint'].rotation_limit_max.z(), 3)}" + ) + model.comment += f"\r\n縲縲縲縲{logger.transtext('縺ー縺ュ(遘サ蜍氷)')}: {round(param_option['horizonal_joint'].spring_constant_translation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍漂)')}: {round(param_option['horizonal_joint'].spring_constant_translation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍瓢)')}: {round(param_option['horizonal_joint'].spring_constant_translation.z(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「X)')}: {round(param_option['horizonal_joint'].spring_constant_rotation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Y)')}: {round(param_option['horizonal_joint'].spring_constant_rotation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Z)')}: {round(param_option['horizonal_joint'].spring_constant_rotation.z(), 3)}" + + if param_option["diagonal_joint"]: + model.comment += f"\r\n縲縲{logger.transtext('譁懊a繧ク繝ァ繧、繝ウ繝')}" + model.comment += f", {logger.transtext('蛻カ髯蝉ソよ焚')}: {round(param_option['diagonal_joint_coefficient'], 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('遘サ蜍氷(譛蟆)')}: {round(param_option['diagonal_joint'].translation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛蟆)')}: {round(param_option['diagonal_joint'].translation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛蟆)')}: {round(param_option['diagonal_joint'].translation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍氷(譛螟ァ)')}: {round(param_option['diagonal_joint'].translation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛螟ァ)')}: {round(param_option['diagonal_joint'].translation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛螟ァ)')}: {round(param_option['diagonal_joint'].translation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('蝗櫁サ「X(譛蟆)')}: {round(param_option['diagonal_joint'].rotation_limit_min.x(), 3)}" + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛蟆)')}: {round(param_option['diagonal_joint'].rotation_limit_min.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛蟆)')}: {round(param_option['diagonal_joint'].rotation_limit_min.z(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「X(譛螟ァ)')}: {round(param_option['diagonal_joint'].rotation_limit_max.x(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Y(譛螟ァ)')}: {round(param_option['diagonal_joint'].rotation_limit_max.y(), 3)}" + ) + model.comment += ( + f", {logger.transtext('蝗櫁サ「Z(譛螟ァ)')}: {round(param_option['diagonal_joint'].rotation_limit_max.z(), 3)}" + ) + model.comment += f"\r\n縲縲縲縲{logger.transtext('縺ー縺ュ(遘サ蜍氷)')}: {round(param_option['diagonal_joint'].spring_constant_translation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍漂)')}: {round(param_option['diagonal_joint'].spring_constant_translation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍瓢)')}: {round(param_option['diagonal_joint'].spring_constant_translation.z(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「X)')}: {round(param_option['diagonal_joint'].spring_constant_rotation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Y)')}: {round(param_option['diagonal_joint'].spring_constant_rotation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Z)')}: {round(param_option['diagonal_joint'].spring_constant_rotation.z(), 3)}" + + if param_option["vertical_reverse_joint"]: + model.comment += f"\r\n縲縲{logger.transtext('邵ヲ騾繧ク繝ァ繧、繝ウ繝')}" + model.comment += ( + f", {logger.transtext('蛻カ髯蝉ソよ焚')}: {round(param_option['vertical_reverse_joint_coefficient'], 3)}" + ) + model.comment += f"\r\n縲縲縲縲{logger.transtext('遘サ蜍氷(譛蟆)')}: {round(param_option['vertical_reverse_joint'].translation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛蟆)')}: {round(param_option['vertical_reverse_joint'].translation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛蟆)')}: {round(param_option['vertical_reverse_joint'].translation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍氷(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].translation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].translation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].translation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('蝗櫁サ「X(譛蟆)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Y(譛蟆)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Z(譛蟆)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「X(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Y(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Z(譛螟ァ)')}: {round(param_option['vertical_reverse_joint'].rotation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('縺ー縺ュ(遘サ蜍氷)')}: {round(param_option['vertical_reverse_joint'].spring_constant_translation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍漂)')}: {round(param_option['vertical_reverse_joint'].spring_constant_translation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍瓢)')}: {round(param_option['vertical_reverse_joint'].spring_constant_translation.z(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「X)')}: {round(param_option['vertical_reverse_joint'].spring_constant_rotation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Y)')}: {round(param_option['vertical_reverse_joint'].spring_constant_rotation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Z)')}: {round(param_option['vertical_reverse_joint'].spring_constant_rotation.z(), 3)}" + + if param_option["horizonal_reverse_joint"]: + model.comment += f"\r\n縲縲{logger.transtext('讓ェ騾繧ク繝ァ繧、繝ウ繝')}" + model.comment += ( + f", {logger.transtext('蛻カ髯蝉ソよ焚')}: {round(param_option['horizonal_reverse_joint_coefficient'], 3)}" + ) + model.comment += f"\r\n縲縲縲縲{logger.transtext('遘サ蜍氷(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍氷(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍漂(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('遘サ蜍瓢(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].translation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('蝗櫁サ「X(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_min.x(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Y(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_min.y(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Z(譛蟆)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_min.z(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「X(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_max.x(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Y(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_max.y(), 3)}" + model.comment += f", {logger.transtext('蝗櫁サ「Z(譛螟ァ)')}: {round(param_option['horizonal_reverse_joint'].rotation_limit_max.z(), 3)}" + model.comment += f"\r\n縲縲縲縲{logger.transtext('縺ー縺ュ(遘サ蜍氷)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_translation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍漂)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_translation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(遘サ蜍瓢)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_translation.z(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「X)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_rotation.x(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Y)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_rotation.y(), 3)}" + model.comment += f", {logger.transtext('縺ー縺ュ(蝗櫁サ「Z)')}: {round(param_option['horizonal_reverse_joint'].spring_constant_rotation.z(), 3)}" material_name = param_option["material_name"] @@ -765,11 +942,19 @@ def create_physics(self, model: PmxModel, param_option: dict): logger.transtext("閭ク") ]: # 閭ク縺ョ蝣エ蜷医¨蠑上♀縺」縺ア縺讒矩繝懊シ繝ウ縺ィ繧ヲ繧ァ繧、繝医r險ュ螳壹☆繧 - virtual_vertices, vertex_maps, all_regist_bones, all_bone_connected, root_bone = self.create_bone_map( + ( + virtual_vertices, + vertex_maps, + all_regist_bones, + all_bone_connected, + root_bone, + is_material_horizonal, + ) = self.create_bone_map( model, param_option, material_name, target_vertices, + MVector3D(0, 0, -1), is_root_bone=(param_option["parent_type"] == logger.transtext("荳ュ蠢")), ) @@ -783,15 +968,31 @@ def create_physics(self, model: PmxModel, param_option: dict): ) else: if param_option["exist_physics_clear"] == logger.transtext("蜀榊茜逕ィ"): - virtual_vertices, vertex_maps, all_regist_bones, all_bone_connected, root_bone = self.create_bone_map( + ( + virtual_vertices, + vertex_maps, + all_regist_bones, + all_bone_connected, + root_bone, + is_material_horizonal, + ) = self.create_bone_map( model, param_option, material_name, target_vertices, + base_vertical_axis, is_root_bone=(param_option["parent_type"] == logger.transtext("荳ュ蠢")), ) else: - vertex_maps, virtual_vertices, remaining_vertices, back_vertices, threshold = self.create_vertex_map( + ( + vertex_maps, + virtual_vertices, + remaining_vertices, + back_vertices, + threshold, + is_material_horizonal, + horizonal_top_edge_keys, + ) = self.create_vertex_map( model, param_option, material_name, @@ -824,7 +1025,14 @@ def create_physics(self, model: PmxModel, param_option: dict): all_bone_horizonal_distances, all_bone_connected, ) = self.create_bone( - model, param_option, material_name, virtual_vertices, vertex_maps, vertex_map_orders, threshold + model, + param_option, + material_name, + virtual_vertices, + vertex_maps, + vertex_map_orders, + threshold, + base_vertical_axis, ) remaining_vertices = self.create_weight( @@ -841,33 +1049,39 @@ def create_physics(self, model: PmxModel, param_option: dict): threshold, ) - # 谿九え繧ァ繧、繝 - weighted_vidxs = self.create_remaining_weight( + # 繧ー繝ゥ繝繧ヲ繧ァ繧、繝 + remaining_vertices = self.create_grad_weight( model, param_option, - material_name, + target_vertices, virtual_vertices, - vertex_maps, - all_regist_bones, remaining_vertices, threshold, + base_vertical_axis, + horizonal_top_edge_keys, ) - # 繧ー繝ゥ繝繧ヲ繧ァ繧、繝 - self.create_grad_weight( + # 陬上え繧ァ繧、繝 + remaining_vidxs = self.create_back_weight( model, param_option, - material_name, - virtual_vertices, target_vertices, - weighted_vidxs, + virtual_vertices, + back_vertices, + remaining_vertices, threshold, - base_vertical_axis, ) - # 陬上え繧ァ繧、繝 - self.create_back_weight( - model, param_option, material_name, virtual_vertices, back_vertices, weighted_vidxs, threshold + # 谿九え繧ァ繧、繝 + self.create_remaining_weight( + model, + param_option, + material_name, + virtual_vertices, + vertex_maps, + all_regist_bones, + remaining_vidxs, + threshold, ) root_rigidbody, parent_bone_rigidbody = self.create_rigidbody( @@ -879,7 +1093,9 @@ def create_physics(self, model: PmxModel, param_option: dict): all_regist_bones, all_bone_connected, root_bone, + base_vertical_axis, base_reverse_axis, + is_material_horizonal, ) self.create_joint( @@ -1045,8 +1261,13 @@ def create_joint( param_option["horizonal_reverse_joint"], vv_keys, param_option["horizonal_reverse_joint_coefficient"] ) - for v_yidx in range(vertex_map.shape[0]): - for v_xidx in range(vertex_map.shape[1]): + for v_xidx in range(vertex_map.shape[1]): + # 螳滄圀縺ォ蜑帑ス薙r菴懊▲縺ヲ繧区怙蠕後ョY + actual_v_yidx = ( + np.min(np.sort(np.where(regist_bones[:, v_xidx])[0])[-2:]) if regist_bones[:, v_xidx].any() else 0 + ) + + for v_yidx in range(vertex_map.shape[0]): if np.isnan(vertex_map[v_yidx, v_xidx]).any(): continue @@ -1058,8 +1279,8 @@ def create_joint( logger.warning("繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", bone_key) continue - if not vv.map_rigidbodies.get(base_map_idx, None): - # 蜑帑ス薙ッ縺上▲縺、縺縺ヲ縺ェ縺蝣エ蜷医′縺ゅk縺ョ縺ァ縲√◎縺ョ蝣エ蜷医ッ繝ッ繝シ繝九Φ繧ー縺ッ蜃コ縺輔★縺ォ繧ケ繝ォ繝シ + if not regist_bones[v_yidx, v_xidx]: + # 繝懊シ繝ウ縺後↑縺蝣エ蜷医ず繝ァ繧、繝ウ繝医ッ荳崎ヲ continue # 隕ェ蜑帑ス薙ョ險育ョ礼畑繧ォ繝励そ繝ォ @@ -1071,7 +1292,6 @@ def create_joint( parent_capsule = MCapsule( MSegment( mat * MVector3D(-parent_bone_rigidbody.shape_size.y(), 0, 0), - parent_bone_rigidbody.shape_position, mat * MVector3D(parent_bone_rigidbody.shape_size.y(), 0, 0), ), parent_bone_rigidbody.shape_size.x(), @@ -1095,7 +1315,36 @@ def create_joint( max_v_yidx, max_v_xidx, ) = self.get_block_vidxs( - v_yidx, v_xidx, vertex_maps, all_regist_bones, all_bone_connected, base_map_idx + v_yidx, + v_xidx, + vertex_maps, + all_regist_bones, + all_bone_connected, + base_map_idx, + ) + + prev_above_vv = ( + virtual_vertices[tuple(vertex_maps[prev_map_idx][above_yidx, prev_xidx])] + if prev_map_idx in vertex_maps + and above_yidx < vertex_maps[prev_map_idx].shape[0] + and prev_xidx < vertex_maps[prev_map_idx].shape[1] + else VirtualVertex("") + ) + + prev_now_vv = ( + virtual_vertices[tuple(vertex_maps[prev_map_idx][v_yidx, prev_xidx])] + if prev_map_idx in vertex_maps + and v_yidx < vertex_maps[prev_map_idx].shape[0] + and prev_xidx < vertex_maps[prev_map_idx].shape[1] + else VirtualVertex("") + ) + + prev_below_vv = ( + virtual_vertices[tuple(vertex_maps[prev_map_idx][below_yidx, prev_xidx])] + if prev_map_idx in vertex_maps + and below_yidx < vertex_maps[prev_map_idx].shape[0] + and prev_xidx < vertex_maps[prev_map_idx].shape[1] + else VirtualVertex("") ) now_above_vv = ( @@ -1151,28 +1400,46 @@ def create_joint( if v_yidx == 0: a_rigidbody = root_rigidbody b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + a_xidx = v_xidx + a_yidx = -1 + b_xidx = v_xidx + b_yidx = v_yidx else: a_rigidbody = now_above_vv.map_rigidbodies.get(base_map_idx, None) + if not a_rigidbody: + # 繧ケ繝ェ繝繝医〒荳翫ョ蜑帑ス薙′隕九▽縺九i縺ェ縺蝣エ蜷医√イ縺ィ縺、蜑阪ョ鬆らせ繝槭ャ繝励r遒コ隱阪☆繧 + a_rigidbody = now_above_vv.map_rigidbodies.get(base_map_idx - 1, None) b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + a_xidx = v_xidx + a_yidx = above_yidx + b_xidx = v_xidx + b_yidx = v_yidx - if not (a_rigidbody and a_rigidbody.index >= 0): + if not (a_rigidbody and a_rigidbody.index >= 0 and b_rigidbody and b_rigidbody.index >= 0): if not ( - regist_bones[below_yidx, v_xidx] - and a_rigidbody + a_rigidbody and b_rigidbody and b_rigidbody.index >= 0 and a_rigidbody.index != b_rigidbody.index ): - logger.warning( - "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n" - + "邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n" - + "鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\n" - + "None縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s", - vv.map_bones[base_map_idx].name - if vv.map_bones.get(base_map_idx, None) - else vv.vidxs(), - decoration=MLogger.DECORATION_BOX, - ) + if v_yidx == 0: + logger.warning( + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶\n" + + "邵ヲ繧ク繝ァ繧、繝ウ繝医′縺ェ縺縺ィ縲∫黄逅縺後メ繝シ繧コ縺ョ繧医≧縺ォ莨ク縺ウ繧句庄閭ス諤ァ縺後≠繧翫∪縺吶\n" + + "鬆らせ繝槭ャ繝励〒荳陦檎岼シ域ケ蜈シ峨′None縺ョ隕∫エ縺後↑縺縺狗「コ隱阪@縺ヲ縺上□縺輔>縲\n" + + "None縺ョ隕∫エ縺梧ケ蜈縺ォ縺ゅj縲√°縺、譬ケ蜈イSV縺梧悴謖螳壹ョ蝣エ蜷医∵ケ蜈イSV繧呈欠螳壹@縺ヲ荳九&縺縲ゅ蜃ヲ逅蟇セ雎。: %s", + vv.map_bones[base_map_idx].name + if vv.map_bones.get(base_map_idx, None) + else vv.vidxs(), + decoration=MLogger.DECORATION_BOX, + ) + elif v_yidx < registed_max_v_yidx: + logger.warning( + "邵ヲ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶ゅ蜃ヲ逅蟇セ雎。: %s", + vv.map_bones[base_map_idx].name + if vv.map_bones.get(base_map_idx, None) + else vv.vidxs(), + ) else: a_bone = model.bones[model.bone_indexes[a_rigidbody.bone_index]] b_bone = model.bones[model.bone_indexes[b_rigidbody.bone_index]] @@ -1214,6 +1481,8 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "竊", 10, @@ -1222,12 +1491,17 @@ def create_joint( b_rigidbody, joint_pos, joint_qq, - vertical_limit_min_mov_xs, - vertical_limit_min_mov_ys, - vertical_limit_min_mov_zs, - vertical_limit_max_mov_xs, - vertical_limit_max_mov_ys, - vertical_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + vertical_limit_min_mov_xs * bone_distance, + vertical_limit_min_mov_ys * bone_distance, + vertical_limit_min_mov_zs * bone_distance, + vertical_limit_max_mov_xs * bone_distance, + vertical_limit_max_mov_ys * bone_distance, + vertical_limit_max_mov_zs * bone_distance, vertical_limit_min_rot_xs, vertical_limit_min_rot_ys, vertical_limit_min_rot_zs, @@ -1241,12 +1515,21 @@ def create_joint( vertical_spring_constant_rot_ys, vertical_spring_constant_rot_zs, ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint if param_option["vertical_reverse_joint"]: # 邵ヲ騾繧ク繝ァ繧、繝ウ繝 a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) b_rigidbody = now_above_vv.map_rigidbodies.get(base_map_idx, None) + # 繧ケ繝ェ繝繝医〒荳翫ョ蜑帑ス薙′隕九▽縺九i縺ェ縺蝣エ蜷医√イ縺ィ縺、蜑阪ョ鬆らせ繝槭ャ繝励r遒コ隱阪☆繧 + if not b_rigidbody: + b_rigidbody = now_above_vv.map_rigidbodies.get(base_map_idx - 1, None) + + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = v_xidx + b_yidx = above_yidx a_bone = model.bones[model.bone_indexes[a_rigidbody.bone_index]] b_bone = model.bones[model.bone_indexes[b_rigidbody.bone_index]] @@ -1285,6 +1568,8 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "竊", 11, @@ -1293,12 +1578,17 @@ def create_joint( b_rigidbody, joint_pos, joint_qq, - vertical_reverse_limit_min_mov_xs, - vertical_reverse_limit_min_mov_ys, - vertical_reverse_limit_min_mov_zs, - vertical_reverse_limit_max_mov_xs, - vertical_reverse_limit_max_mov_ys, - vertical_reverse_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + vertical_reverse_limit_min_mov_xs * bone_distance, + vertical_reverse_limit_min_mov_ys * bone_distance, + vertical_reverse_limit_min_mov_zs * bone_distance, + vertical_reverse_limit_max_mov_xs * bone_distance, + vertical_reverse_limit_max_mov_ys * bone_distance, + vertical_reverse_limit_max_mov_zs * bone_distance, vertical_reverse_limit_min_rot_xs, vertical_reverse_limit_min_rot_ys, vertical_reverse_limit_min_rot_zs, @@ -1312,13 +1602,19 @@ def create_joint( vertical_reverse_spring_constant_rot_ys, vertical_reverse_spring_constant_rot_zs, ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint # 繝舌Λ繝ウ繧オ繝シ蜑帑ス薙′蠢隕√↑蝣エ蜷 if param_option["rigidbody_balancer"]: a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) b_rigidbody = now_now_vv.map_balance_rigidbodies.get(base_map_idx, None) + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = v_xidx + b_yidx = v_yidx + if not ( a_rigidbody and b_rigidbody @@ -1353,6 +1649,11 @@ def create_joint( b_rigidbody, a_rigidbody.shape_position.copy(), MQuaternion(), + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, [0], [0], [0], @@ -1372,11 +1673,17 @@ def create_joint( [100000], [100000], ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint a_rigidbody = now_above_vv.map_balance_rigidbodies.get(base_map_idx, None) b_rigidbody = now_now_vv.map_balance_rigidbodies.get(base_map_idx, None) + a_xidx = v_xidx + a_yidx = above_yidx + b_xidx = v_xidx + b_yidx = v_yidx + if ( a_rigidbody and b_rigidbody @@ -1393,6 +1700,11 @@ def create_joint( b_rigidbody, MVector3D(), MQuaternion(), + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, [-50], [-50], [-50], @@ -1412,24 +1724,47 @@ def create_joint( [0], [0], ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint - if param_option["horizonal_joint"] and next_connected and next_now_vv and not is_center: + if param_option["horizonal_joint"] and not is_center: # 讓ェ繧ク繝ァ繧、繝ウ繝 a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) b_rigidbody = next_now_vv.map_rigidbodies.get(next_map_idx, None) - if not (a_rigidbody and b_rigidbody and a_rigidbody.index >= 0 and b_rigidbody.index >= 0): + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = next_xidx + b_yidx = v_yidx + + if not b_rigidbody or (not next_connected and prev_connected): + # 讓ェ縺後↑縺蝣エ蜷医√b縺励¥縺ッ郢九′縺」縺ヲ縺ェ縺蝣エ蜷医∝・繧梧崛縺医k + a_rigidbody = prev_now_vv.map_rigidbodies.get(prev_map_idx, None) + b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + + a_xidx = prev_xidx + a_yidx = v_yidx + b_xidx = v_xidx + b_yidx = v_yidx + + if v_yidx < registed_max_v_yidx and not ( + a_rigidbody and b_rigidbody and a_rigidbody.index >= 0 and b_rigidbody.index >= 0 + ): logger.warning( "讓ェ繧ク繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", vv.map_bones[base_map_idx].name if vv.map_bones.get(base_map_idx, None) else vv.vidxs(), ) + # elif not ( + # v_xidx < vertex_map.shape[1] - 1 or (v_xidx == vertex_map.shape[1] - 1 and next_connected) + # ): + # # 遶ッ縺ョ蝣エ蜷医ッ譛蛻昴→郢九′縺」縺ヲ縺繧九%縺ィ繧呈擅莉カ縺ィ縺吶k + # pass elif a_rigidbody and b_rigidbody and a_rigidbody.index == b_rigidbody.index: # 蜷後§蜑帑ス薙↑縺ョ縺ッ蜷御ク鬆らせ縺九i繝懊シ繝ウ縺悟コ繧句エ蜷医↓譛峨j蠕励k縺ョ縺ァ縲∬ュヲ蜻翫ッ蜃コ縺輔↑縺 pass - else: + elif v_yidx < registed_max_v_yidx: a_bone = model.bones[model.bone_indexes[a_rigidbody.bone_index]] b_bone = model.bones[model.bone_indexes[b_rigidbody.bone_index]] if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢"): @@ -1475,7 +1810,6 @@ def create_joint( a_capsule = MCapsule( MSegment( a_mat * MVector3D(-a_length, 0, 0), - a_rigidbody.shape_position, a_mat * MVector3D(a_length, 0, 0), ), a_length * check_ratio, @@ -1495,7 +1829,6 @@ def create_joint( b_capsule = MCapsule( MSegment( b_mat * MVector3D(-b_length, 0, 0), - b_rigidbody.shape_position, b_mat * MVector3D(b_length, 0, 0), ), b_length * check_ratio, @@ -1514,6 +1847,8 @@ def create_joint( ) break + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "竊", 21, @@ -1522,12 +1857,17 @@ def create_joint( b_rigidbody, joint_pos, joint_qq, - horizonal_limit_min_mov_xs, - horizonal_limit_min_mov_ys, - horizonal_limit_min_mov_zs, - horizonal_limit_max_mov_xs, - horizonal_limit_max_mov_ys, - horizonal_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + horizonal_limit_min_mov_xs * bone_distance, + horizonal_limit_min_mov_ys * bone_distance, + horizonal_limit_min_mov_zs * bone_distance, + horizonal_limit_max_mov_xs * bone_distance, + horizonal_limit_max_mov_ys * bone_distance, + horizonal_limit_max_mov_zs * bone_distance, horizonal_limit_min_rot_xs, horizonal_limit_min_rot_ys, horizonal_limit_min_rot_zs, @@ -1542,13 +1882,27 @@ def create_joint( horizonal_spring_constant_rot_zs, ratio, ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint + + if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") and v_yidx == actual_v_yidx: + # 陬セ讓ェ繧ク繝ァ繧、繝ウ繝 + # 縺イ縺ィ縺、荳翫ョ繝懊シ繝ウ縺ォ邏蝉サ倥¥繧ク繝ァ繧、繝ウ繝医r繝√ぉ繝繧ッ + a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + b_rigidbody = next_now_vv.map_rigidbodies.get(next_map_idx, None) + + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = next_xidx + b_yidx = v_yidx if ( - param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") - and v_yidx == registed_max_v_yidx + next_connected + and a_rigidbody + and b_rigidbody + and a_rigidbody.index >= 0 + and b_rigidbody.index >= 0 ): - # 譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝 a_pos = ( model.bones[ model.bone_indexes[ @@ -1556,7 +1910,7 @@ def create_joint( ] ].position if model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index >= 0 - else model.bone_indexes[a_rigidbody.bone_index].position + else model.bones[model.bone_indexes[a_rigidbody.bone_index]].position + model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_position ) @@ -1567,7 +1921,7 @@ def create_joint( ] ].position if model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index >= 0 - else model.bone_indexes[b_rigidbody.bone_index].position + else model.bones[model.bone_indexes[b_rigidbody.bone_index]].position + model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_position ) @@ -1582,20 +1936,27 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "竊", - 22, + 21, bone_y_idx, a_rigidbody, b_rigidbody, joint_pos, joint_qq, - horizonal_limit_min_mov_xs, - horizonal_limit_min_mov_ys, - horizonal_limit_min_mov_zs, - horizonal_limit_max_mov_xs, - horizonal_limit_max_mov_ys, - horizonal_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx + 1, + b_xidx, + b_yidx + 1, + horizonal_limit_min_mov_xs * bone_distance, + horizonal_limit_min_mov_ys * bone_distance, + horizonal_limit_min_mov_zs * bone_distance, + horizonal_limit_max_mov_xs * bone_distance, + horizonal_limit_max_mov_ys * bone_distance, + horizonal_limit_max_mov_zs * bone_distance, horizonal_limit_min_rot_xs, horizonal_limit_min_rot_ys, horizonal_limit_min_rot_zs, @@ -1611,37 +1972,83 @@ def create_joint( ratio, override_joint_name=f"竊竹{a_bone.name}T|{b_bone.name}T", ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint - if param_option["horizonal_reverse_joint"]: - # 讓ェ騾繧ク繝ァ繧、繝ウ繝 - a_rigidbody = next_now_vv.map_rigidbodies.get(next_map_idx, None) - b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + last_v_xidx = np.max(np.sort(np.where(regist_bones[v_yidx, :])[0])[-2:]) + ( + last_prev_map_idx, + last_prev_xidx, + last_prev_connected, + last_next_map_idx, + last_next_xidx, + last_next_connected, + last_above_yidx, + last_below_yidx, + last_target_v_yidx, + last_target_v_xidx, + last_registed_max_v_yidx, + last_registed_max_v_xidx, + last_max_v_yidx, + last_max_v_xidx, + ) = self.get_block_vidxs( + v_yidx, + last_v_xidx, + vertex_maps, + all_regist_bones, + all_bone_connected, + base_map_idx, + is_center=is_center, + ) - a_bone = model.bones[model.bone_indexes[a_rigidbody.bone_index]] - b_bone = model.bones[model.bone_indexes[b_rigidbody.bone_index]] - if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢"): - # 蜑帑ス薙′驥阪↑繧狗ョ謇縺ョ莠、轤ケ - above_mat = MMatrix4x4() - above_point = MVector3D() - if a_rigidbody: - above_mat.setToIdentity() - above_mat.translate(a_rigidbody.shape_position) - above_mat.rotate(a_rigidbody.shape_qq) - above_point = above_mat * MVector3D(-a_rigidbody.shape_size.x(), 0, 0) + if ( + param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") + and v_xidx == registed_max_v_xidx + ): + # 讓ェ譛ォ遶ッ繧ク繝ァ繧、繝ウ繝 + # 縺イ縺ィ縺、荳翫ョ繝懊シ繝ウ縺ォ邏蝉サ倥¥繧ク繝ァ繧、繝ウ繝医r繝√ぉ繝繧ッ + a_rigidbody = prev_now_vv.map_rigidbodies.get(prev_map_idx, None) + b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) - now_mat = MMatrix4x4() - now_mat.setToIdentity() - now_mat.translate(b_rigidbody.shape_position) - now_mat.rotate(b_rigidbody.shape_qq) - now_point = now_mat * MVector3D(b_rigidbody.shape_size.x(), 0, 0) + a_xidx = prev_xidx + a_yidx = v_yidx + b_xidx = v_xidx + b_yidx = v_yidx - joint_pos = (above_point + now_point) / 2 - else: - joint_pos = b_bone.position + if ( + not next_connected + and prev_connected + and a_rigidbody + and b_rigidbody + and a_rigidbody.index >= 0 + and b_rigidbody.index >= 0 + ): + a_pos = ( + model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index + ] + ].position + if model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index >= 0 + else model.bones[model.bone_indexes[a_rigidbody.bone_index]].position + + model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_position + ) + + b_pos = ( + model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index + ] + ].position + if model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index >= 0 + else model.bones[model.bone_indexes[b_rigidbody.bone_index]].position + + model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_position + ) + + joint_pos = b_pos # 繝懊シ繝ウ騾イ陦梧婿蜷(x) - x_direction_pos = (b_bone.position - a_bone.position).normalized() + x_direction_pos = (b_pos - a_pos).normalized() # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) z_direction_pos = ( (a_rigidbody.z_direction + b_rigidbody.z_direction) / 2 @@ -1649,54 +2056,233 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( - "竊", - 23, + "竊", + 22, bone_y_idx, a_rigidbody, b_rigidbody, joint_pos, joint_qq, - horizonal_reverse_limit_min_mov_xs, - horizonal_reverse_limit_min_mov_ys, - horizonal_reverse_limit_min_mov_zs, - horizonal_reverse_limit_max_mov_xs, - horizonal_reverse_limit_max_mov_ys, - horizonal_reverse_limit_max_mov_zs, - horizonal_reverse_limit_min_rot_xs, - horizonal_reverse_limit_min_rot_ys, - horizonal_reverse_limit_min_rot_zs, - horizonal_reverse_limit_max_rot_xs, - horizonal_reverse_limit_max_rot_ys, - horizonal_reverse_limit_max_rot_zs, - horizonal_reverse_spring_constant_mov_xs, - horizonal_reverse_spring_constant_mov_ys, - horizonal_reverse_spring_constant_mov_zs, - horizonal_reverse_spring_constant_rot_xs, - horizonal_reverse_spring_constant_rot_ys, - horizonal_reverse_spring_constant_rot_zs, + base_map_idx, + a_xidx, + a_yidx + 1, + b_xidx, + b_yidx + 1, + horizonal_limit_min_mov_xs * bone_distance, + horizonal_limit_min_mov_ys * bone_distance, + horizonal_limit_min_mov_zs * bone_distance, + horizonal_limit_max_mov_xs * bone_distance, + horizonal_limit_max_mov_ys * bone_distance, + horizonal_limit_max_mov_zs * bone_distance, + horizonal_limit_min_rot_xs, + horizonal_limit_min_rot_ys, + horizonal_limit_min_rot_zs, + horizonal_limit_max_rot_xs, + horizonal_limit_max_rot_ys, + horizonal_limit_max_rot_zs, + horizonal_spring_constant_mov_xs, + horizonal_spring_constant_mov_ys, + horizonal_spring_constant_mov_zs, + horizonal_spring_constant_rot_xs, + horizonal_spring_constant_rot_ys, + horizonal_spring_constant_rot_zs, ratio, + override_joint_name=f"竊竹{a_bone.name}T|{b_bone.name}T", ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint - if ( - param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") - and v_yidx == registed_max_v_yidx - ): - # 譛ォ遶ッ讓ェ騾繧ク繝ァ繧、繝ウ繝 - a_bone = model.bones[ - model.bone_indexes[ - model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index - ] - ] - b_bone = model.bones[ - model.bone_indexes[ - model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index - ] - ] - joint_pos = b_bone.position + # --------------------------- + # 讓ェ譛ォ遶ッ騾繧ク繝ァ繧、繝ウ繝 + a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + b_rigidbody = prev_now_vv.map_rigidbodies.get(prev_map_idx, None) - # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = prev_xidx + b_yidx = v_yidx + + if ( + not next_connected + and prev_connected + and a_rigidbody + and b_rigidbody + and a_rigidbody.index >= 0 + and b_rigidbody.index >= 0 + ): + # 譛ォ遶ッ讓ェ騾繧ク繝ァ繧、繝ウ繝 + a_bone = model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index + ] + ] + b_bone = model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index + ] + ] + joint_pos = b_bone.position + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + x_direction_pos = (b_bone.position - a_bone.position).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) + z_direction_pos = ( + (a_rigidbody.z_direction + b_rigidbody.z_direction) / 2 + ).normalized() + joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) + joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + + joint_key, joint = self.build_joint( + "竊", + 23, + bone_y_idx, + a_rigidbody, + b_rigidbody, + joint_pos, + joint_qq, + base_map_idx, + a_xidx, + a_yidx + 1, + b_xidx, + b_yidx + 1, + horizonal_limit_min_mov_xs * bone_distance, + horizonal_limit_min_mov_ys * bone_distance, + horizonal_limit_min_mov_zs * bone_distance, + horizonal_limit_max_mov_xs * bone_distance, + horizonal_limit_max_mov_ys * bone_distance, + horizonal_limit_max_mov_zs * bone_distance, + horizonal_limit_min_rot_xs * 0 + 1, + horizonal_limit_min_rot_ys * 0 + 1, + horizonal_limit_min_rot_zs * 0 + 1, + horizonal_limit_max_rot_xs * 0, + horizonal_limit_max_rot_ys * 0, + horizonal_limit_max_rot_zs * 0, + horizonal_spring_constant_mov_xs, + horizonal_spring_constant_mov_ys, + horizonal_spring_constant_mov_zs, + horizonal_spring_constant_rot_xs * 0, + horizonal_spring_constant_rot_ys * 0, + horizonal_spring_constant_rot_zs * 0, + ratio, + override_joint_name=f"竊酢{a_rigidbody.name}T|{b_rigidbody.name}T", + ) + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint + + if param_option["horizonal_reverse_joint"]: + # 讓ェ騾繧ク繝ァ繧、繝ウ繝 + a_rigidbody = next_now_vv.map_rigidbodies.get(next_map_idx, None) + b_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) + + a_xidx = next_xidx + a_yidx = v_yidx + b_xidx = v_xidx + b_yidx = v_yidx + + if a_rigidbody and b_rigidbody and a_rigidbody.index >= 0 and b_rigidbody.index >= 0: + a_bone = model.bones[model.bone_indexes[a_rigidbody.bone_index]] + b_bone = model.bones[model.bone_indexes[b_rigidbody.bone_index]] + if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢"): + # 蜑帑ス薙′驥阪↑繧狗ョ謇縺ョ莠、轤ケ + above_mat = MMatrix4x4() + above_point = MVector3D() + if a_rigidbody: + above_mat.setToIdentity() + above_mat.translate(a_rigidbody.shape_position) + above_mat.rotate(a_rigidbody.shape_qq) + above_point = above_mat * MVector3D(-a_rigidbody.shape_size.x(), 0, 0) + + now_mat = MMatrix4x4() + now_mat.setToIdentity() + now_mat.translate(b_rigidbody.shape_position) + now_mat.rotate(b_rigidbody.shape_qq) + now_point = now_mat * MVector3D(b_rigidbody.shape_size.x(), 0, 0) + + joint_pos = (above_point + now_point) / 2 + else: + joint_pos = b_bone.position + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + x_direction_pos = (b_bone.position - a_bone.position).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) + z_direction_pos = ( + (a_rigidbody.z_direction + b_rigidbody.z_direction) / 2 + ).normalized() + joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) + joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + + joint_key, joint = self.build_joint( + "竊", + 23, + bone_y_idx, + a_rigidbody, + b_rigidbody, + joint_pos, + joint_qq, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + horizonal_reverse_limit_min_mov_xs * bone_distance, + horizonal_reverse_limit_min_mov_ys * bone_distance, + horizonal_reverse_limit_min_mov_zs * bone_distance, + horizonal_reverse_limit_max_mov_xs * bone_distance, + horizonal_reverse_limit_max_mov_ys * bone_distance, + horizonal_reverse_limit_max_mov_zs * bone_distance, + horizonal_reverse_limit_min_rot_xs, + horizonal_reverse_limit_min_rot_ys, + horizonal_reverse_limit_min_rot_zs, + horizonal_reverse_limit_max_rot_xs, + horizonal_reverse_limit_max_rot_ys, + horizonal_reverse_limit_max_rot_zs, + horizonal_reverse_spring_constant_mov_xs, + horizonal_reverse_spring_constant_mov_ys, + horizonal_reverse_spring_constant_mov_zs, + horizonal_reverse_spring_constant_rot_xs, + horizonal_reverse_spring_constant_rot_ys, + horizonal_reverse_spring_constant_rot_zs, + ratio, + ) + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint + + if ( + param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") + and v_yidx == registed_max_v_yidx + ): + # 譛ォ遶ッ讓ェ繧ク繝ァ繧、繝ウ繝 + # 縺イ縺ィ縺、荳翫ョ繝懊シ繝ウ縺ォ邏蝉サ倥¥繧ク繝ァ繧、繝ウ繝医r繝√ぉ繝繧ッ + a_rigidbody = next_above_vv.map_rigidbodies.get(next_map_idx, None) + b_rigidbody = now_above_vv.map_rigidbodies.get(base_map_idx, None) + + a_xidx = next_xidx + a_yidx = above_yidx + b_xidx = v_xidx + b_yidx = above_yidx + + if a_rigidbody and b_rigidbody and a_rigidbody.index >= 0 and b_rigidbody.index >= 0: + # 譛ォ遶ッ讓ェ騾繧ク繝ァ繧、繝ウ繝 + a_bone = model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[a_rigidbody.bone_index]].tail_index + ] + ] + b_bone = model.bones[ + model.bone_indexes[ + model.bones[model.bone_indexes[b_rigidbody.bone_index]].tail_index + ] + ] + joint_pos = b_bone.position + + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) x_direction_pos = (b_bone.position - a_bone.position).normalized() # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) z_direction_pos = ( @@ -1705,20 +2291,27 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "竊", - 24, + 23, bone_y_idx, a_rigidbody, b_rigidbody, joint_pos, joint_qq, - horizonal_limit_min_mov_xs, - horizonal_limit_min_mov_ys, - horizonal_limit_min_mov_zs, - horizonal_limit_max_mov_xs, - horizonal_limit_max_mov_ys, - horizonal_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx + 1, + b_xidx, + b_yidx + 1, + horizonal_limit_min_mov_xs * bone_distance, + horizonal_limit_min_mov_ys * bone_distance, + horizonal_limit_min_mov_zs * bone_distance, + horizonal_limit_max_mov_xs * bone_distance, + horizonal_limit_max_mov_ys * bone_distance, + horizonal_limit_max_mov_zs * bone_distance, horizonal_limit_min_rot_xs, horizonal_limit_min_rot_ys, horizonal_limit_min_rot_zs, @@ -1732,15 +2325,21 @@ def create_joint( horizonal_spring_constant_rot_ys, horizonal_spring_constant_rot_zs, ratio, - override_joint_name=f"竊酢{a_bone.name}|{b_bone.name}", + override_joint_name=f"竊酢{a_bone.name}T|{b_bone.name}T", ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint if param_option["diagonal_joint"] and next_connected and next_below_vv and not is_center: # 譁懊a繧ク繝ァ繧、繝ウ繝 a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) b_rigidbody = next_below_vv.map_rigidbodies.get(next_map_idx, None) + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = next_xidx + b_yidx = below_yidx + if not ( a_rigidbody and b_rigidbody @@ -1749,9 +2348,10 @@ def create_joint( and a_rigidbody.index != b_rigidbody.index ): if ( - regist_bones.shape[0] > below_yidx + regist_bones.shape[0] - 1 > below_yidx and regist_bones.shape[1] > next_xidx and regist_bones[below_yidx, next_xidx] + and v_yidx < registed_max_v_yidx ): logger.warning( "譁懊aシ茨シシシ峨ず繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", @@ -1794,6 +2394,8 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "シシ", 31, @@ -1802,12 +2404,17 @@ def create_joint( b_rigidbody, joint_pos, joint_qq, - diagonal_limit_min_mov_xs, - diagonal_limit_min_mov_ys, - diagonal_limit_min_mov_zs, - diagonal_limit_max_mov_xs, - diagonal_limit_max_mov_ys, - diagonal_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + diagonal_limit_min_mov_xs * bone_distance, + diagonal_limit_min_mov_ys * bone_distance, + diagonal_limit_min_mov_zs * bone_distance, + diagonal_limit_max_mov_xs * bone_distance, + diagonal_limit_max_mov_ys * bone_distance, + diagonal_limit_max_mov_zs * bone_distance, diagonal_limit_min_rot_xs, diagonal_limit_min_rot_ys, diagonal_limit_min_rot_zs, @@ -1821,7 +2428,8 @@ def create_joint( diagonal_spring_constant_rot_ys, diagonal_spring_constant_rot_zs, ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint if ( param_option["diagonal_joint"] @@ -1834,6 +2442,11 @@ def create_joint( a_rigidbody = now_now_vv.map_rigidbodies.get(base_map_idx, None) b_rigidbody = next_above_vv.map_rigidbodies.get(next_map_idx, None) + a_xidx = v_xidx + a_yidx = v_yidx + b_xidx = next_xidx + b_yidx = above_yidx + if not ( a_rigidbody and b_rigidbody @@ -1845,9 +2458,10 @@ def create_joint( regist_bones.shape[0] > above_yidx and regist_bones.shape[1] > v_xidx and regist_bones[above_yidx, v_xidx] + and v_yidx < registed_max_v_yidx ): logger.warning( - "譁懊aシ茨シシシ峨ず繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", + "譁懊aシ茨シ擾シ峨ず繝ァ繧、繝ウ繝育函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", vv.map_bones[base_map_idx].name if vv.map_bones.get(base_map_idx, None) else vv.vidxs(), @@ -1887,6 +2501,8 @@ def create_joint( joint_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) joint_qq *= MQuaternion.fromEulerAngles(180, 0, 0) + bone_distance = a_bone.position.distanceToPoint(b_bone.position) + joint_key, joint = self.build_joint( "シ", 32, @@ -1895,12 +2511,17 @@ def create_joint( b_rigidbody, joint_pos, joint_qq, - diagonal_limit_min_mov_xs, - diagonal_limit_min_mov_ys, - diagonal_limit_min_mov_zs, - diagonal_limit_max_mov_xs, - diagonal_limit_max_mov_ys, - diagonal_limit_max_mov_zs, + base_map_idx, + a_xidx, + a_yidx, + b_xidx, + b_yidx, + diagonal_limit_min_mov_xs * bone_distance, + diagonal_limit_min_mov_ys * bone_distance, + diagonal_limit_min_mov_zs * bone_distance, + diagonal_limit_max_mov_xs * bone_distance, + diagonal_limit_max_mov_ys * bone_distance, + diagonal_limit_max_mov_zs * bone_distance, diagonal_limit_min_rot_xs, diagonal_limit_min_rot_ys, diagonal_limit_min_rot_zs, @@ -1914,7 +2535,8 @@ def create_joint( diagonal_spring_constant_rot_ys, diagonal_spring_constant_rot_zs, ) - created_joints[joint_key] = joint + if joint.name not in [j.name for j in created_joints.values()]: + created_joints[joint_key] = joint if len(created_joints) > 0 and len(created_joints) // 50 > prev_joint_cnt: logger.info("-- -- 縲侵o.%s縲代ず繝ァ繧、繝ウ繝: %s蛟狗岼:邨ゆコ", base_map_idx + 1, len(created_joints)) @@ -1943,6 +2565,11 @@ def build_joint( b_rigidbody: RigidBody, joint_pos: MVector3D, joint_qq: MQuaternion, + base_map_idx: int, + a_xidx: int, + a_yidx: int, + b_xidx: int, + b_yidx: int, limit_min_mov_xs: np.ndarray, limit_min_mov_ys: np.ndarray, limit_min_mov_zs: np.ndarray, @@ -2344,7 +2971,9 @@ def create_rigidbody( all_regist_bones: dict, all_bone_connected: dict, root_bone: Bone, + base_vertical_axis: MVector3D, base_reverse_axis: MVector3D, + is_material_horizonal: bool, ): logger.info("縲%s:%s縲大央菴鍋函謌", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) @@ -2393,6 +3022,9 @@ def create_rigidbody( model.rigidbodies[parent_bone.name] = parent_bone_rigidbody + # 蜈ィ髱櫁。晉ェ∝ッセ雎。 + all_no_collision_group = 0 + top_bone_positions = [] for vertex_map in vertex_maps.values(): for vkey in vertex_map[0, :]: @@ -2460,7 +3092,7 @@ def create_rigidbody( ) # rigidbody_size_ratios = np.linspace(1, 0.7, len(v_yidxs)) - for v_yidx in range(vertex_map.shape[0]): + for v_yidx in range(vertex_map.shape[0] - 1): for v_xidx in range(vertex_map.shape[1]): if np.isnan(vertex_map[v_yidx, v_xidx]).any() or not regist_bones[v_yidx, v_xidx]: continue @@ -2468,9 +3100,6 @@ def create_rigidbody( rigidbody_bone_key = tuple(vertex_map[v_yidx, v_xidx]) vv = virtual_vertices.get(rigidbody_bone_key, None) - if vv.map_rigidbodies: - continue - if not vv: logger.warning( "蜑帑ス鍋函謌舌↓蠢隕√↑諠蝣ア縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", @@ -2504,12 +3133,25 @@ def create_rigidbody( ) below_yidx = below_yidx if below_yidx > v_yidx else max_v_yidx + # now_below_connected = all_bone_connected[base_map_idx][ + # below_yidx, + # v_xidx, + # ] + prev_below_connected = all_bone_connected[prev_map_idx][ + min(below_yidx, all_bone_connected[prev_map_idx].shape[0] - 1), + min(prev_xidx, all_bone_connected[prev_map_idx].shape[1] - 1), + ] + next_below_connected = all_bone_connected[next_map_idx][ + min(below_yidx, all_bone_connected[next_map_idx].shape[0] - 1), + min(next_xidx, all_bone_connected[next_map_idx].shape[1] - 1), + ] prev_above_vv = ( virtual_vertices[tuple(vertex_maps[prev_map_idx][above_yidx, prev_xidx])] if prev_map_idx in vertex_maps and above_yidx < vertex_maps[prev_map_idx].shape[0] and prev_xidx < vertex_maps[prev_map_idx].shape[1] + and above_yidx < v_yidx else VirtualVertex("") ) @@ -2526,6 +3168,7 @@ def create_rigidbody( if prev_map_idx in vertex_maps and below_yidx < vertex_maps[prev_map_idx].shape[0] and prev_xidx < vertex_maps[prev_map_idx].shape[1] + and below_yidx > v_yidx else VirtualVertex("") ) @@ -2534,6 +3177,7 @@ def create_rigidbody( if base_map_idx in vertex_maps and above_yidx < vertex_maps[base_map_idx].shape[0] and v_xidx < vertex_maps[base_map_idx].shape[1] + and above_yidx < v_yidx else VirtualVertex("") ) @@ -2550,6 +3194,7 @@ def create_rigidbody( if base_map_idx in vertex_maps and below_yidx < vertex_maps[base_map_idx].shape[0] and v_xidx < vertex_maps[base_map_idx].shape[1] + and below_yidx > v_yidx else VirtualVertex("") ) @@ -2558,6 +3203,7 @@ def create_rigidbody( if next_map_idx in vertex_maps and above_yidx < vertex_maps[next_map_idx].shape[0] and next_xidx < vertex_maps[next_map_idx].shape[1] + and above_yidx < v_yidx else VirtualVertex("") ) @@ -2574,6 +3220,7 @@ def create_rigidbody( if next_map_idx in vertex_maps and below_yidx < vertex_maps[next_map_idx].shape[0] and next_xidx < vertex_maps[next_map_idx].shape[1] + and below_yidx > v_yidx else VirtualVertex("") ) @@ -2596,18 +3243,25 @@ def create_rigidbody( next_now_bone = next_now_vv.map_bones.get(next_map_idx, None) next_below_bone = next_below_vv.map_bones.get(next_map_idx, None) + last_v_xidx = np.max(np.sort(np.where(regist_bones[v_yidx, :])[0])[-2:]) + if not (now_now_bone and now_below_bone): - logger.warning( - "蜑帑ス鍋函謌舌↓蠢隕√↑諠蝣ア(繝懊シ繝ウ)縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", - vv.map_bones[base_map_idx].name if vv.map_bones.get(base_map_idx, None) else vv.vidxs(), - ) + if now_now_bone.getVisibleFlag(): + logger.warning( + "蜑帑ス鍋函謌舌↓蠢隕√↑諠蝣ア(繝懊シ繝ウ)縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲√せ繝ォ繝シ縺励∪縺吶 蜃ヲ逅蟇セ雎。: %s", + vv.map_bones[base_map_idx].name + if vv.map_bones.get(base_map_idx, None) + else vv.vidxs(), + ) continue if not (now_now_bone.index in model.vertices): # 繧ヲ繧ァ繧、繝医r謖√▲縺ヲ縺ェ縺繝懊シ繝ウ縺ッ逋サ骭イ蟇セ雎。螟厄シ域怏繧雁セ励k縺ョ縺ァ隴ヲ蜻翫↑縺暦シ continue + x_ratio = 0.5 if is_center: + # 荳ュ螟ョ縺ッ蜈ィ驛ィ繧定ヲ縺 x_sizes = [] if prev_now_vv and next_now_vv: x_sizes.append(next_now_vv.position().distanceToPoint(prev_now_vv.position())) @@ -2616,53 +3270,60 @@ def create_rigidbody( elif not prev_now_vv and next_now_vv: x_sizes.append(next_now_vv.position().distanceToPoint(now_now_vv.position())) x_size = np.max(x_sizes) if x_sizes else 0.2 - - elif next_connected: - x_sizes = [] - if next_now_bone: - x_sizes.append(now_now_bone.position.distanceToPoint(next_now_bone.position)) - if next_below_bone: - x_sizes.append(now_below_bone.position.distanceToPoint(next_below_bone.position)) - x_size = np.max(x_sizes) if x_sizes else 0.2 - elif prev_connected and v_xidx > 0: - if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢"): - x_sizes = [] - if prev_now_bone: - x_sizes.append(now_now_bone.position.distanceToPoint(prev_now_bone.position)) - if prev_below_bone: - x_sizes.append(now_below_bone.position.distanceToPoint(prev_below_bone.position)) - x_size = np.max(x_sizes) if x_sizes else 0.2 - else: - x_size = 0.2 else: - v_poses = [(v.position * base_reverse_axis).data() for v in model.vertices[now_now_bone.index]] + # 縺昴l莉・螟悶ッ縺ィ繧翫≠縺医★髫」縺ョ莉ョ諠ウ鬆らせ縺九i讓ェ蟷繧貞峙繧 + if next_now_vv.position() != MVector3D() and ( + v_xidx < last_v_xidx or (v_xidx == last_v_xidx and next_connected) + ): + x_sizes = [now_now_bone.position.distanceToPoint(next_now_vv.position())] + x_sizes.append(now_below_vv.position().distanceToPoint(next_below_vv.position())) + x_size = np.mean(x_sizes) + elif ( + (v_xidx < last_v_xidx or (v_xidx == last_v_xidx and next_connected)) + and now_below_vv.position() != MVector3D() + and next_below_vv.position() != MVector3D() + ): + x_size = now_below_vv.position().distanceToPoint(next_below_vv.position()) + elif ( + v_xidx > 0 or (v_xidx == 0 and prev_connected) + ) and prev_now_vv.position() != MVector3D(): + x_sizes = [now_now_bone.position.distanceToPoint(prev_now_vv.position())] + if ( + now_below_vv.position() != MVector3D() + and prev_below_vv.position() != MVector3D() + and (v_xidx > 0 or (v_xidx == 0 and prev_connected)) + ): + x_sizes.append(now_below_vv.position().distanceToPoint(prev_below_vv.position())) + x_size = np.mean(x_sizes) + elif ( + (v_xidx > 0 or (v_xidx == 0 and prev_below_connected)) + and now_below_vv.position() != MVector3D() + and prev_below_vv.position() != MVector3D() + ): + x_size = now_below_vv.position().distanceToPoint(prev_below_vv.position()) + else: + v_poses = [ + (v.position * base_reverse_axis).data() for v in model.vertices[now_now_bone.index] + ] - # # 谺。縺ィ郢九′縺」縺ヲ縺繧句エ蜷医∵ャ。縺ョ繝懊シ繝ウ縺ョ鬆らせ繧定ソス蜉縺吶k - # if next_connected and next_now_bone and next_now_bone.index in model.vertices: - # v_poses += [(v.position * base_reverse_axis).data() for v in model.vertices[next_now_bone.index]] + # # 谺。縺ィ郢九′縺」縺ヲ縺繧句エ蜷医∵ャ。縺ョ繝懊シ繝ウ縺ョ鬆らせ繧定ソス蜉縺吶k + # if next_connected and next_now_bone and next_now_bone.index in model.vertices: + # v_poses += [(v.position * base_reverse_axis).data() for v in model.vertices[next_now_bone.index]] - # 驥崎、縺ッ髯、螟 - v_poses = np.unique(v_poses, axis=0) + # 驥崎、縺ッ髯、螟 + v_poses = np.unique(v_poses, axis=0) - # 蜑帑ス薙ョ蟷 - all_vertex_diffs = np.expand_dims(v_poses, axis=1) - np.expand_dims(v_poses, axis=0) - all_vertex_distances = np.sqrt(np.sum(all_vertex_diffs**2, axis=-1)) - x_size = np.median(all_vertex_distances) + # 蜑帑ス薙ョ蟷 + all_vertex_diffs = np.expand_dims(v_poses, axis=1) - np.expand_dims(v_poses, axis=0) + all_vertex_distances = np.sqrt(np.sum(all_vertex_diffs**2, axis=-1)) + x_size = np.median(all_vertex_distances) - if now_above_bone and now_below_bone: - # 荳贋ク区純縺」縺ヲ繧句エ蜷医‖verage - y_size = np.max( - [ - now_now_bone.position.distanceToPoint(now_above_bone.position), - now_now_bone.position.distanceToPoint(now_below_bone.position), - ], - ) - elif now_below_bone: - # 縺昴ョ莉悶ッ荳九ョ繝懊シ繝ウ縺ィ縺ョ霍晞屬 - y_size = now_now_bone.position.distanceToPoint(now_below_bone.position) + if now_below_vv.position() != MVector3D(): + # 蝓コ譛ャ縺ッ荳九ョ繝懊シ繝ウ縺ィ縺ョ霍晞屬 + y_size = now_now_bone.position.distanceToPoint(now_below_vv.position()) else: - # 譛ォ遶ッ縺ッ荳翫→縺ョ髟キ縺輔↓縺励※縺翫¥ - y_size = now_now_bone.position.distanceToPoint(now_above_bone.position) + # 荳翫→郢九′縺」縺ヲ縺繧句エ蜷 + y_size = now_now_bone.position.distanceToPoint(now_above_vv.position()) if rigidbody_shape_type == 0: # 逅蜑帑ス薙ョ蝣エ蜷 @@ -2673,8 +3334,8 @@ def create_rigidbody( elif rigidbody_shape_type == 1: # 邂ア蜑帑ス薙ョ蝣エ蜷 shape_size = MVector3D( - x_size * (0.5 if next_connected or prev_connected else 1), - max(0.25, y_size) * (0.5 if v_yidx > 0 else 0.25), + max(0.5, x_size) * x_ratio, + max(0.5, y_size) * 0.5, rigidbody_limit_thicks[v_yidx], ) shape_volume = shape_size.x() * shape_size.y() * shape_size.z() @@ -2689,7 +3350,7 @@ def create_rigidbody( 4 / 3 * math.pi * shape_size.x() ) - logger.debug( + logger.test( "name: %s, size: %s, volume: %s", vv.map_bones[base_map_idx].name, shape_size.to_log(), @@ -2702,114 +3363,231 @@ def create_rigidbody( round(shape_volume, 5), ) - if v_xidx == registed_max_v_xidx: - # 蜀蜻ィ繧呈緒縺縺ヲ縺繧句エ蜷医∵怙蛻晢シ域怙蠕後ョ谺。シ峨°繧峨ョ荳ュ髢薙↓縺励※縺翫¥ - if next_connected: - mean_x_idx = v_xidx + (max_v_xidx + 1 - v_xidx) / 2 - else: - mean_x_idx = v_xidx - else: - mean_x_idx = v_xidx + (next_xidx - v_xidx) / 2 - mean_y_idx = v_yidx + (below_yidx - v_yidx) / 2 - - floor_mean_xidx = math.floor(mean_x_idx) - ceil_mean_xidx = math.ceil(mean_x_idx) - if ceil_mean_xidx >= vertex_map.shape[1]: - # 譛蠕後r雜縺医※縺繧句エ蜷医∵怙蛻昴↓謌サ縺 - ceil_mean_xidx = 0 + # if v_xidx == registed_max_v_xidx: + # # 蜀蜻ィ繧呈緒縺縺ヲ縺繧句エ蜷医∵怙蛻晢シ域怙蠕後ョ谺。シ峨°繧峨ョ荳ュ髢薙↓縺励※縺翫¥ + # if next_connected: + # mean_x_idx = v_xidx + (max_v_xidx + 1 - v_xidx) / 2 + # else: + # mean_x_idx = v_xidx - 0.5 + # else: + # mean_x_idx = v_xidx + (next_xidx - v_xidx) / 2 + # mean_y_idx = v_yidx + (below_yidx - v_yidx) / 2 + + # floor_mean_xidx = int(mean_x_idx - 1) if mean_x_idx % 1 == 0 else math.floor(mean_x_idx) + # ceil_mean_xidx = int(mean_x_idx + 1) if mean_x_idx % 1 == 0 else math.ceil(mean_x_idx) + # if ceil_mean_xidx >= vertex_map.shape[1]: + # if len(vertex_maps) == 1: + # # 譛蠕後r雜縺医※縺繧句エ蜷医∝蜻ィシ磯らせ繝槭ャ繝励′1縺、シ峨ッ譛蛻昴↓謌サ縺 + # ceil_mean_xidx = 0 + # else: + # # 繧ケ繝ェ繝繝医↑縺ゥ縺ョ蝣エ蜷医√イ縺ィ縺、縺壹▽蜑阪↓縺壹i縺 + # floor_mean_xidx = math.floor(mean_x_idx - 1) + # ceil_mean_xidx = math.ceil(mean_x_idx - 1) if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢"): # 繧ク繝ァ繧、繝ウ繝医′繝懊シ繝ウ髢薙↓縺ゅk蝣エ蜷医∝央菴薙ッ繝懊シ繝ウ菴咲スョ - shape_position = now_now_bone.position + if is_material_horizonal: + # 蟷ウ陦後〒縺ゅk蝣エ蜷医∽ク九懊シ繝ウ縺ィ縺ョ荳ュ髢 + shape_position = (now_now_bone.position + now_below_bone.position) / 2 + else: + # 蟷ウ陦後〒縺ッ縺ェ縺蝣エ蜷医∝セ後〒隱ソ謨エ縺礼峩縺吶ョ縺ァ荳譌ヲ繝懊シ繝ウ菴咲スョ + shape_position = now_now_bone.position else: - if param_option["exist_physics_clear"] in [logger.transtext("縺昴ョ縺セ縺セ"), logger.transtext("荳頑嶌縺")]: - # 縺昴ョ縺セ縺セ繝サ荳頑嶌縺阪ッ繝。繝繧キ繝・縺ョ荳ュ髢謎ス咲スョ縺ァ菴咲スョ繧貞叙繧顔峩縺 - shape_positions = [] - if tuple(vertex_map[math.floor(mean_y_idx), floor_mean_xidx]) in virtual_vertices: - shape_positions.append( - virtual_vertices[tuple(vertex_map[math.floor(mean_y_idx), floor_mean_xidx])] - .position() - .data() - ) - if tuple(vertex_map[math.floor(mean_y_idx), ceil_mean_xidx]) in virtual_vertices: - shape_positions.append( - virtual_vertices[tuple(vertex_map[math.floor(mean_y_idx), ceil_mean_xidx])] - .position() - .data() - ) - if tuple(vertex_map[math.ceil(mean_y_idx), floor_mean_xidx]) in virtual_vertices: - shape_positions.append( - virtual_vertices[tuple(vertex_map[math.ceil(mean_y_idx), floor_mean_xidx])] - .position() - .data() - ) - if tuple(vertex_map[math.ceil(mean_y_idx), ceil_mean_xidx]) in virtual_vertices: - shape_positions.append( - virtual_vertices[tuple(vertex_map[math.ceil(mean_y_idx), ceil_mean_xidx])] - .position() - .data() - ) + # 繝懊シ繝ウ菴咲スョ縺ッ隍謨ー縺ョ繝懊シ繝ウ縺ョ荳ュ螟ョ縺ォ蜑帑ス薙r驟咲スョ縺吶k + shape_positions = [] + shape_positions.append(now_now_bone.position) - shape_position = MVector3D( - np.mean( - shape_positions, - axis=0, - ) - ) - else: - # 蜀榊茜逕ィ縺ッ繝懊シ繝ウ縺ョ菴咲スョ縺縺代〒蛻、螳 - shape_positions = [] - shape_positions.append(now_now_bone.position) - if now_above_bone and now_now_bone == now_below_bone: - shape_positions.append(now_above_bone.position.data()) - else: - shape_positions.append(now_below_bone.position.data()) - if next_now_bone: - shape_positions.append(next_now_bone.position.data()) - elif prev_now_bone: - shape_positions.append(prev_now_bone.position.data()) - if next_below_bone: - shape_positions.append(next_below_bone.position.data()) - elif prev_below_bone: - shape_positions.append(prev_below_bone.position.data()) - shape_position = MVector3D(np.mean(shape_positions, axis=0)) - - if v_yidx == max_v_yidx or now_now_bone == now_below_bone: - # 譛ォ遶ッ縺ッ霆ク譁ケ蜷代′縺イ縺ィ縺、荳翫ョ蜷代″縺ィ縺吶k - x_direction_to_pos = now_above_bone.position - x_direction_from_pos = y_direction_from_pos = now_now_bone.position - if tuple(vertex_map[above_yidx, ceil_mean_xidx]) in virtual_vertices: - y_direction_to_pos = virtual_vertices[ - tuple(vertex_map[above_yidx, ceil_mean_xidx]) - ].position() + if now_above_bone and now_now_bone == now_below_bone: + # 譛ォ遶ッ縺ョ蝣エ蜷医∽ク翫ョ繝懊シ繝ウ縺ィ縺ョ菴咲スョ繧呈クャ繧 + if now_above_vv.position() != MVector3D(): + shape_positions.append(now_above_vv.position()) + + if next_connected: + if next_now_vv.position() != MVector3D(): + shape_positions.append(next_now_vv.position()) + + if next_above_vv.position() != MVector3D(): + shape_positions.append(next_above_vv.position()) else: - y_direction_to_pos = y_direction_from_pos + MVector3D(1, 0, 0) + # 縺昴l莉・螟悶ョ蝣エ蜷医∽ク九ョ繝懊シ繝ウ縺ィ縺ョ菴咲スョ繧呈クャ繧 + if now_below_vv.position() != MVector3D(): + shape_positions.append(now_below_vv.position()) + + if next_connected: + if next_now_vv.position() != MVector3D(): + shape_positions.append(next_now_vv.position()) + + if next_below_vv.position() != MVector3D(): + shape_positions.append(next_below_vv.position()) + + elif prev_connected: + # 谺。縺ィ郢九′縺」縺ヲ縺ェ縺蝣エ蜷医∝燕縺ィ郢九£繧 + if prev_now_vv.position() != MVector3D(): + shape_positions.append(prev_now_vv.position()) + + if prev_below_vv.position() != MVector3D(): + shape_positions.append(prev_below_vv.position()) + + # if now_above_bone and now_now_bone == now_below_bone: + # shape_positions.append(now_above_bone.position.data()) + # if now_below_bone: + # shape_positions.append(now_below_bone.position.data()) + + # if next_connected and next_now_bone: + # shape_positions.append(next_now_bone.position.data()) + # # elif prev_connected and prev_now_bone: + # # shape_positions.append(prev_now_bone.position.data()) + + # if next_below_connected and next_below_bone: + # shape_positions.append(next_below_bone.position.data()) + # # elif prev_below_connected and prev_below_bone: + # # shape_positions.append(prev_below_bone.position.data()) + + shape_position = MVector3D(np.mean(shape_positions, axis=0)) + + # if param_option["exist_physics_clear"] in [logger.transtext("縺昴ョ縺セ縺セ"), logger.transtext("荳頑嶌縺")]: + # # 縺昴ョ縺セ縺セ繝サ荳頑嶌縺阪ッ繝。繝繧キ繝・縺ョ荳ュ髢謎ス咲スョ縺ァ菴咲スョ繧貞叙繧顔峩縺 + # shape_positions = [] + # if now_now_bone: + # shape_positions.append(now_now_bone.position) + # if now_below_bone: + # shape_positions.append(now_below_bone.position) + # if next_now_bone: + # shape_positions.append(next_now_bone.position) + # if next_below_bone: + # shape_positions.append(next_below_bone.position) + + # # if tuple(vertex_map[math.floor(mean_y_idx), floor_mean_xidx]) in virtual_vertices: + # # shape_positions.append( + # # virtual_vertices[tuple(vertex_map[math.floor(mean_y_idx), floor_mean_xidx])] + # # .position() + # # .data() + # # ) + # # if tuple(vertex_map[math.floor(mean_y_idx), ceil_mean_xidx]) in virtual_vertices: + # # shape_positions.append( + # # virtual_vertices[tuple(vertex_map[math.floor(mean_y_idx), ceil_mean_xidx])] + # # .position() + # # .data() + # # ) + # # if tuple(vertex_map[math.ceil(mean_y_idx), floor_mean_xidx]) in virtual_vertices: + # # shape_positions.append( + # # virtual_vertices[tuple(vertex_map[math.ceil(mean_y_idx), floor_mean_xidx])] + # # .position() + # # .data() + # # ) + # # if tuple(vertex_map[math.ceil(mean_y_idx), ceil_mean_xidx]) in virtual_vertices: + # # shape_positions.append( + # # virtual_vertices[tuple(vertex_map[math.ceil(mean_y_idx), ceil_mean_xidx])] + # # .position() + # # .data() + # # ) + + # shape_position = MVector3D( + # np.mean( + # shape_positions, + # axis=0, + # ) + # ) + # else: + # # 蜀榊茜逕ィ縺ッ繝懊シ繝ウ縺ョ菴咲スョ縺縺代〒蛻、螳 + # shape_positions = [] + # shape_positions.append(now_now_bone.position) + # if now_above_bone and now_now_bone == now_below_bone: + # shape_positions.append(now_above_bone.position.data()) + # else: + # shape_positions.append(now_below_bone.position.data()) + # if next_now_bone: + # shape_positions.append(next_now_bone.position.data()) + # elif prev_now_bone: + # shape_positions.append(prev_now_bone.position.data()) + # if next_below_bone: + # shape_positions.append(next_below_bone.position.data()) + # elif prev_below_bone: + # shape_positions.append(prev_below_bone.position.data()) + # shape_position = MVector3D(np.mean(shape_positions, axis=0)) + + # if v_yidx == max_v_yidx or now_now_bone == now_below_bone: + # # 譛ォ遶ッ縺ッ霆ク譁ケ蜷代′縺イ縺ィ縺、荳翫ョ蜷代″縺ィ縺吶k + # x_direction_to_pos = now_above_bone.position + # x_direction_from_pos = y_direction_to_pos = now_now_bone.position + # if tuple(vertex_map[above_yidx, ceil_mean_xidx]) in virtual_vertices: + # y_direction_from_pos = virtual_vertices[ + # tuple(vertex_map[above_yidx, ceil_mean_xidx]) + # ].position() + # else: + # is_y_direction_prev = True + # y_direction_from_pos = virtual_vertices[ + # tuple(vertex_map[above_yidx, floor_mean_xidx]) + # ].position() + # else: + + is_y_direction_prev = False + y_direction_from_pos = now_below_bone.position + + if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") and next_connected: + # 繝懊シ繝ウ菴咲スョ縺ョ蝣エ蜷医∵ャ。繝懊シ繝ウ縺ィ縺ョ髢薙r騾イ陦梧婿蜷代→縺吶k + x_direction_from_pos = (now_below_vv.position() + next_below_vv.position()) / 2 + x_direction_to_pos = (now_now_bone.position + next_now_vv.position()) / 2 + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) + y_direction_to_pos = next_below_vv.position() + y_direction_pos = (y_direction_to_pos - y_direction_from_pos).normalized() + elif param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") and prev_connected: + # 谺。縺ィ郢九′縺」縺ヲ縺ェ縺蝣エ蜷医∝燕縺ィ郢九£繧 + x_direction_from_pos = (now_below_vv.position() + prev_below_vv.position()) / 2 + x_direction_to_pos = (now_now_bone.position + prev_now_vv.position()) / 2 + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) + y_direction_to_pos = prev_below_vv.position() + y_direction_pos = (y_direction_to_pos - y_direction_from_pos).normalized() + is_y_direction_prev = True else: + x_direction_from_pos = now_below_vv.position() x_direction_to_pos = now_now_bone.position - x_direction_from_pos = y_direction_from_pos = now_below_bone.position - if ( - tuple(vertex_map[v_yidx, ceil_mean_xidx]) in virtual_vertices - and virtual_vertices[tuple(vertex_map[v_yidx, ceil_mean_xidx])].position() - != now_now_bone.position - ): - y_direction_to_pos = virtual_vertices[tuple(vertex_map[v_yidx, ceil_mean_xidx])].position() - else: - y_direction_to_pos = y_direction_from_pos + MVector3D(1, 0, 0) + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + x_direction_pos = (x_direction_to_pos - x_direction_from_pos).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) + # 螟也ゥ阪°繧我サョ縺ョ讓ェ霆ク繧呈アゅa繧 + y_direction_pos = MVector3D.crossProduct(x_direction_pos, base_vertical_axis).normalized() # 繝懊シ繝ウ騾イ陦梧婿蜷(x) x_direction_pos = (x_direction_to_pos - x_direction_from_pos).normalized() - # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) - y_direction_pos = (y_direction_to_pos - y_direction_from_pos).normalized() + + # if ( + # tuple(vertex_map[v_yidx, ceil_mean_xidx]) in virtual_vertices + # and virtual_vertices[tuple(vertex_map[v_yidx, ceil_mean_xidx])].position() + # != now_now_bone.position + # ): + # y_direction_from_pos = virtual_vertices[tuple(vertex_map[v_yidx, ceil_mean_xidx])].position() + # else: + # is_y_direction_prev = True + # y_direction_from_pos = virtual_vertices[tuple(vertex_map[v_yidx, floor_mean_xidx])].position() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) - z_direction_pos = MVector3D.crossProduct(x_direction_pos, y_direction_pos) - shape_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) - shape_qq *= MQuaternion.fromEulerAngles(0, 180, 0) - shape_euler = shape_qq.toEulerAngles() + z_direction_pos = MVector3D.crossProduct(x_direction_pos, y_direction_pos).normalized() + + if is_material_horizonal: + shape_qq = MQuaternion.rotationTo(MVector3D(0, 0, 1), x_direction_pos) + # shape_qq *= MQuaternion.fromEulerAngles(90, 0, 0) + y_euler = ( + 90 * -x_direction_pos.y() + if np.isclose(abs(x_direction_pos.y()), 1) + else shape_qq.toEulerAngles().y() + ) + shape_qq = MQuaternion.fromEulerAngles(90, -y_euler, 0) + shape_euler = MVector3D(90, y_euler, 0) + else: + shape_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) + if is_y_direction_prev: + shape_qq *= MQuaternion.fromEulerAngles(0, 180, 0) + shape_euler = shape_qq.toEulerAngles() shape_rotation_radians = MVector3D( math.radians(shape_euler.x()), math.radians(shape_euler.y()), math.radians(shape_euler.z()) ) - if param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢") and rigidbody_shape_type == 1: + if ( + param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ髢") + and rigidbody_shape_type == 1 + and not is_material_horizonal + ): if v_yidx == 0: # 繝懊シ繝ウ髢薙ョ邂ア蜑帑ス薙ョ譬ケ蜈縺ッ蜑帑ス謎ス咲スョ繧剃クュ髢薙↓譚・繧九h縺隱ソ謨エ mat = MMatrix4x4() @@ -2829,21 +3607,134 @@ def create_rigidbody( mat.rotate(now_above_vv.map_rigidbodies[base_map_idx].shape_qq) mat.translate(MVector3D(0, -now_above_vv.map_rigidbodies[base_map_idx].shape_size.y(), 0)) shape_position = mat * MVector3D(0, -shape_size.y(), 0) + elif ( + now_above_vv + and base_map_idx - 1 in now_above_vv.map_rigidbodies + and now_above_vv.map_rigidbodies[base_map_idx - 1].name in created_rigidbodies + ): + # 荳ュ髢薙ッ荳翫ョ蜑帑ス薙ョ遶ッ縺九i險育ョ励@縺ェ縺翫☆ + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(now_above_vv.map_rigidbodies[base_map_idx - 1].shape_position) + mat.rotate(now_above_vv.map_rigidbodies[base_map_idx - 1].shape_qq) + mat.translate( + MVector3D(0, -now_above_vv.map_rigidbodies[base_map_idx - 1].shape_size.y(), 0) + ) + shape_position = mat * MVector3D(0, -shape_size.y(), 0) + + # if ( + # param_option["joint_pos_type"] == logger.transtext("繝懊シ繝ウ菴咲スョ") + # and rigidbody_shape_type == 1 + # and not next_connected + # and prev_connected + # ): + # # 繝懊シ繝ウ菴咲スョ縺ァ谺。縺檎ケ九′縺」縺ヲ縺ェ縺蝣エ蜷医々霆ク譁ケ蜷代↓遘サ蜍輔&縺帙k + # mat = MMatrix4x4() + # mat.setToIdentity() + # mat.translate(shape_position) + # mat.rotate(shape_qq) + # shape_position = mat * MVector3D(shape_size.x(), 0, 0) # 譬ケ蜈縺ッ迚ゥ逅貍皮ョ + Bone菴咲スョ蜷医o縺帙√◎繧御サ・髯阪ッ迚ゥ逅蜑帑ス mode = 2 if 0 == v_yidx else 1 + # 蜑阪〒郢九′縺」縺ヲ縺ェ縺Ч + prev_not_connected_x_idxs = np.where( + np.diff(all_bone_connected[base_map_idx][v_yidx, :v_xidx]) == -1 + )[0] + prev_not_connected_x_idx = ( + np.max(prev_not_connected_x_idxs + 1) if prev_not_connected_x_idxs.any() else 0 + ) + # 閾ェ蛻繧貞性繧蠕後〒郢九′縺」縺ヲ縺ェ縺Ч + next_not_connected_x_idxs = np.where( + np.diff(all_bone_connected[base_map_idx][v_yidx, (prev_not_connected_x_idx + 1) :]) == -1 + )[0] + next_not_connected_x_idx = ( + np.min(next_not_connected_x_idxs + (prev_not_connected_x_idx + 1) + 1) + if next_not_connected_x_idxs.any() + else 0 + ) + next_not_connected_prev_x_idx = ( + np.max(np.where(regist_bones[v_yidx, :next_not_connected_x_idx])[0]) + if next_not_connected_x_idx + else 0 + ) + + # 螳滄圀縺ォ蜑帑ス薙r菴懊▲縺ヲ繧区怙蠕後ョY + actual_v_yidx = np.min(np.sort(np.where(regist_bones[:, v_xidx])[0])[-2:]) + + ( + last_prev_map_idx, + last_prev_xidx, + last_prev_connected, + last_next_map_idx, + last_next_xidx, + last_next_connected, + last_above_yidx, + last_below_yidx, + last_target_v_yidx, + last_target_v_xidx, + last_registed_max_v_yidx, + last_registed_max_v_xidx, + last_max_v_yidx, + last_max_v_xidx, + ) = self.get_block_vidxs( + v_yidx, + last_v_xidx, + vertex_maps, + all_regist_bones, + all_bone_connected, + base_map_idx, + is_center=is_center, + ) + + is_folding = v_xidx in [next_not_connected_prev_x_idx, next_not_connected_x_idx,] and param_option[ + "joint_pos_type" + ] == logger.transtext("繝懊シ繝ウ菴咲スョ") + logger.debug( + "is_folding: base_map_idx[%s], v_xidx[%s], v_yidx[%s], is_folding[%s], next_not_connected_prev_x_idx[%s], next_not_connected_x_idx[%s], last_next_connected[%s]", + base_map_idx, + v_xidx, + v_yidx, + is_folding, + next_not_connected_prev_x_idx, + next_not_connected_x_idx, + last_next_connected, + ) + + # 讓ェ遶ッ縺瑚ェ蛻縺ョ蜈医′郢九′縺」縺ヲ辟。縺蝣エ蜷医∵釜繧願ソ斐@縺ッ雉ェ驥丞濠蛻 + mass_ratio = 0.5 if next_not_connected_x_idx and is_folding else 1 + mass = rigidbody_masses[v_yidx] * mass_ratio + + if is_folding and next_not_connected_x_idx and v_xidx == next_not_connected_x_idx: + # 謚倥j霑斐@縺ョ蝣エ蜷医√イ縺ィ縺、蜑阪→謠縺医k + next_not_connected_prev_x_key = tuple(vertex_map[v_yidx, next_not_connected_prev_x_idx]) + prev_rigidbody = virtual_vertices[next_not_connected_prev_x_key].map_rigidbodies.get(base_map_idx, None) + if prev_rigidbody: + shape_size = prev_rigidbody.shape_size + shape_position = prev_rigidbody.shape_position + shape_rotation_radians = prev_rigidbody.shape_rotation + mass = prev_rigidbody.param.mass + + logger.debug( + "**folding copy: base_map_idx[%s], v_xidx[%s], v_yidx[%s], is_folding[%s]", + base_map_idx, + v_xidx, + v_yidx, + is_folding, + ) + vv.map_rigidbodies[base_map_idx] = RigidBody( vv.map_bones[base_map_idx].name, vv.map_bones[base_map_idx].name, vv.map_bones[base_map_idx].index, param_rigidbody.collision_group, - param_rigidbody.no_collision_group, + (param_rigidbody.no_collision_group if v_yidx < actual_v_yidx else all_no_collision_group), rigidbody_shape_type, shape_size, shape_position, shape_rotation_radians, - rigidbody_masses[v_yidx], + mass, linear_dampings[v_yidx], angular_dampings[v_yidx], param_rigidbody.param.restitution, @@ -2871,7 +3762,7 @@ def create_rigidbody( logger.info("-- -- 縲侵o.%s縲大央菴: %s蛟狗岼:邨ゆコ", base_map_idx + 1, len(created_rigidbodies)) prev_rigidbody_cnt = len(created_rigidbodies) // 50 - for rigidbody_name in sorted(created_rigidbodies.keys()): + for rigidbody_name in created_rigidbodies.keys(): # 蜑帑ス薙r逋サ骭イ rigidbody = created_rigidbodies[rigidbody_name] rigidbody.index = len(model.rigidbodies) @@ -3030,52 +3921,74 @@ def create_grad_weight( self, model: PmxModel, param_option: dict, - material_name: str, + target_vertices: list, virtual_vertices: dict, - target_map_vertices: list, - weighted_vidxs: list, + remaining_vertices: list, threshold: float, base_vertical_axis: MVector3D, + horizonal_top_edge_keys: list, ): - - # 陬城擇蟇セ雎。鬆らせCSV縺梧欠螳壹&繧後※縺縺ェ縺蝣エ蜷医√せ繝ォ繝シ - if not param_option["vertices_csv"]: - return + # 谿矩らせ縺後↑縺繧ゅ@縺上ッ譬ケ蜈鬆らせ縺梧欠螳壹&繧後※縺縺ェ縺蝣エ蜷医√せ繝ォ繝シ + if not remaining_vertices or not param_option["top_vertices_csv"]: + return remaining_vertices logger.info( - "縲%s:%s縲代げ繝ゥ繝繝シ繧キ繝ァ繝ウ繧ヲ繧ァ繧、繝育函謌", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE + "縲%s:%s縲代げ繝ゥ繝繝シ繧キ繝ァ繝ウ繧ヲ繧ァ繧、繝育函謌", + param_option["material_name"], + param_option["abb_name"], + decoration=MLogger.DECORATION_LINE, ) - target_vertices = {} - for vidx in target_map_vertices: - v = model.vertex_dict[vidx] - v_key = v.position.to_key(threshold) - if v.index not in weighted_vidxs: - if v_key not in target_vertices: - # 縺セ縺逋サ骭イ縺輔l縺ヲ縺ェ縺縲√°縺、譌「縺ォ蝪励j邨ゅo縺」縺滄らせ縺ァ縺ッ縺ェ縺蝣エ蜷医∝ッセ雎。 - target_vertices[v_key] = VirtualVertex(v_key) - target_vertices[v_key].append([v], [], []) - - if not target_vertices or not weighted_vidxs: - logger.info("繧ー繝ゥ繝繝シ繧キ繝ァ繝ウ蟇セ雎。鬆らせ縺瑚ヲ九▽縺九i縺ェ縺九▲縺溘◆繧√∝ヲ逅繧偵せ繧ュ繝繝励@縺セ縺") - return - # 隕ェ繝懊シ繝ウ parent_bone = model.bones[param_option["parent_bone_name"]] + # 蝪励j邨ゅo縺」縺滉サョ諠ウ鬆らせ繧ュ繝シ繝ェ繧ケ繝 + weighted_vkeys = list(set(virtual_vertices.keys()) - set(remaining_vertices.keys())) + # 蝪励j邨ゅo縺」縺滄らせ縺ョ繝ェ繧ケ繝 weighted_vertices = {} - for vidx in weighted_vidxs: - v = model.vertex_dict[vidx] - weighted_vertices[v.index] = v.position.data() + for vkey in weighted_vkeys: + for vidx in virtual_vertices[vkey].vidxs(): + v = model.vertex_dict[vidx] + weighted_vertices[v.index] = v.position.data() weight_cnt = 0 prev_weight_cnt = 0 - for v_key, vv in target_vertices.items(): + # 鬆らせ繝槭ャ繝嶺ク企Κ縺ョ菴咲スョ + top_vv_poses = np.array([virtual_vertices[tk].position().data() for tk in horizonal_top_edge_keys]) + + # 隕ェ繝懊シ繝ウ縺ョ隧穂セ。霆ク菴咲スョ + parent_axis_val = parent_bone.position.data()[np.where(np.abs(base_vertical_axis.data()))][0] + # 髮「繧後◆隧穂セ。霆ク + axis_root_val = base_vertical_axis.data()[np.where(np.abs(base_vertical_axis.data()))][0] * 100 + + weighted_grad_vkeys = [] + for v_key, vv in remaining_vertices.items(): if not vv.vidxs(): continue + # 莉ョ諠ウ鬆らせ縺ョ隧穂セ。霆ク菴咲スョ + vv_axis_val = vv.position().data()[np.where(np.abs(base_vertical_axis.data()))][0] + + # 鬆らせ繝槭ャ繝嶺ク企Κ縺ィ縺ョ霍晞屬 + top_distances = np.linalg.norm((top_vv_poses - vv.position().data()), ord=2, axis=1) + nearest_top_vidxs = virtual_vertices[horizonal_top_edge_keys[np.argmin(top_distances)]].vidxs() + nearest_top_pos = top_vv_poses[np.argmin(top_distances)] + # 鬆らせ繝槭ャ繝嶺ク企Κ逶エ霑鷹らせ縺ョ隧穂セ。霆ク菴咲スョ + nearest_top_axis_val = nearest_top_pos[np.where(np.abs(base_vertical_axis.data()))][0] + + if nearest_top_axis_val > vv_axis_val: + # 隧穂セ。霆ク縺ォTOP繧医j驕縺シ医せ繧ォ繝シ繝医ョ蝣エ蜷医ゝOP繧医j荳具シ峨ョ蝣エ蜷医√せ繝ォ繝シ + logger.debug( + f"テ励げ繝ゥ繝繧ケ繝ォ繝シ: target [{vv.vidxs()}], nearest_top_vidxs[{nearest_top_vidxs}], nearest_top_axis_val[{round(nearest_top_axis_val, 3)}], vv[{vv.vidxs()}], vv_axis_val[{round(vv_axis_val, 3)}]" + ) + continue + + logger.debug( + f"笳九げ繝ゥ繝繧ソ繝シ繧イ繝繝: target [{vv.vidxs()}], nearest_top_vidxs[{nearest_top_vidxs}], nearest_top_axis_val[{round(nearest_top_axis_val, 3)}], vv[{vv.vidxs()}], vv_axis_val[{round(vv_axis_val, 3)}], parent_axis_val[{round(parent_axis_val, 3)}]" + ) + # 蜷鬆らせ縺ョ菴咲スョ縺ィ縺ョ蟾ョ蛻縺九i霍晞屬繧呈クャ繧 vv_distances = np.linalg.norm( (np.array(list(weighted_vertices.values())) - vv.position().data()), ord=2, axis=1 @@ -3085,21 +3998,23 @@ def create_grad_weight( copy_weighted_vertex_idx = list(weighted_vertices.keys())[np.argmin(vv_distances)] copy_weighted_vertex = model.vertex_dict[copy_weighted_vertex_idx] - # 隕ェ繝懊シ繝ウ縺ョ隧穂セ。霆ク菴咲スョ - parent_axis_pos = parent_bone.position.data()[np.where(np.abs(base_vertical_axis.data()))][0] # 逶エ霑鷹らせ縺ョ隧穂セ。霆ク菴咲スョ - nearest_vertex_axis_pos = copy_weighted_vertex.position.data()[ + nearest_vertex_axis_val = copy_weighted_vertex.position.data()[ np.where(np.abs(base_vertical_axis.data())) ][0] - # 蜃ヲ逅蟇セ雎。鬆らせ縺ョ隧穂セ。霆ク菴咲スョ - target_axis_pos = vv.position().data()[np.where(np.abs(base_vertical_axis.data()))][0] + # # 蜃ヲ逅蟇セ雎。鬆らせ縺ョ隧穂セ。霆ク菴咲スョ + # target_axis_val = vv.position().data()[np.where(np.abs(base_vertical_axis.data()))][0] # if not nearest_vertex_axis_pos <= target_axis_pos <= parent_axis_pos: # # 蜃ヲ逅蟇セ雎。鬆らせ縺檎ッ蝗イ螟悶ョ蝣エ蜷医√せ繝ォ繝シ # continue # 蜃ヲ逅蟇セ雎。鬆らせ縺ョ逶エ霑鷹らせ繝懊シ繝ウ繧ヲ繧ァ繧、繝域ッ皮紫 - target_ratio = (target_axis_pos - nearest_vertex_axis_pos) / (parent_axis_pos - nearest_vertex_axis_pos) + target_ratio = ( + (vv_axis_val - nearest_vertex_axis_val) / (parent_axis_val - nearest_vertex_axis_val) + if parent_axis_val > vv_axis_val + else 1 + ) # 繧ヲ繧ァ繧、繝域ッ皮紫縺九i繧ヲ繧ァ繧、繝磯上r隱ソ謨エ vertex_weights = np.array(copy_weighted_vertex.deform.get_weights()) * min(1, max(0, (1 - target_ratio))) @@ -3118,62 +4033,69 @@ def create_grad_weight( weights = np.array(list(total_weights.values()))[weight_idxs] # 繧ヲ繧ァ繧、繝域ュ」隕丞喧 weights = weights / weights.sum(axis=0, keepdims=1) - # INDEX蜿悶j逶エ縺暦シ医え繧ァ繧、繝医′5莉カ莉・荳翫≠縺」縺溷エ蜷育畑シ - weight_idxs = np.argsort(-weights) logger.debug( - f"繧ー繝ゥ繝蜈鬆らせ: target [{vv.vidxs()}], weighted [{copy_weighted_vertex_idx}], weight_idx[{weight_bone_idxs}], weight[{np.round(weights, decimals=3)}]" + f"繧ー繝ゥ繝蜈鬆らせ: target [{vv.vidxs()}], weighted [{copy_weighted_vertex_idx}], weight_idx[{weight_bone_idxs}], weight[{np.round(weights, decimals=3)}, ratio[{round(target_ratio, 3)}]]" ) if np.count_nonzero(weights) == 1: - vv.deform = Bdef1(weight_bone_idxs[weight_idxs[-1]]) + vv.deform = Bdef1(weight_bone_idxs[-1]) elif np.count_nonzero(weights) == 2: vv.deform = Bdef2( - weight_bone_idxs[weight_idxs[-1]], - weight_bone_idxs[weight_idxs[-2]], - weights[weight_idxs[-1]], + weight_bone_idxs[-1], + weight_bone_idxs[-2], + weights[-1], ) elif np.count_nonzero(weights) == 3: vv.deform = Bdef4( - weight_bone_idxs[weight_idxs[-1]], - weight_bone_idxs[weight_idxs[-2]], - weight_bone_idxs[weight_idxs[-3]], + weight_bone_idxs[-1], + weight_bone_idxs[-2], + weight_bone_idxs[-3], 0, - weights[weight_idxs[-1]], - weights[weight_idxs[-2]], - weights[weight_idxs[-3]], + weights[-1], + weights[-2], + weights[-3], 0, ) else: vv.deform = Bdef4( - weight_bone_idxs[weight_idxs[-1]], - weight_bone_idxs[weight_idxs[-2]], - weight_bone_idxs[weight_idxs[-3]], - weight_bone_idxs[weight_idxs[-4]], - weights[weight_idxs[-1]], - weights[weight_idxs[-2]], - weights[weight_idxs[-3]], - weights[weight_idxs[-4]], + weight_bone_idxs[-1], + weight_bone_idxs[-2], + weight_bone_idxs[-3], + weight_bone_idxs[-4], + weights[-1], + weights[-2], + weights[-3], + weights[-4], ) for rv in vv.real_vertices: rv.deform = vv.deform + weighted_grad_vkeys.append(v_key) + weight_cnt += 1 if weight_cnt > 0 and weight_cnt // 200 > prev_weight_cnt: logger.info("-- 繧ー繝ゥ繝繝シ繧キ繝ァ繝ウ鬆らせ繧ヲ繧ァ繧、繝: %s蛟狗岼:邨ゆコ", weight_cnt) prev_weight_cnt = weight_cnt // 200 + for v_key in weighted_grad_vkeys: + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if v_key in remaining_vertices: + del remaining_vertices[v_key] + logger.info("-- 繧ー繝ゥ繝繝シ繧キ繝ァ繝ウ鬆らせ繧ヲ繧ァ繧、繝: %s蛟狗岼:邨ゆコ", weight_cnt) + return remaining_vertices + def create_back_weight( self, model: PmxModel, param_option: dict, - material_name: str, + target_vertices: list, virtual_vertices: dict, back_vertices: list, - weighted_vidxs: list, + remaining_vertices: dict, threshold: float, ): if param_option["back_material_name"]: @@ -3188,25 +4110,41 @@ def create_back_weight( for vertices_back_csv_path in glob(param_option["vertices_back_csv"]): back_vertices.extend(read_vertices_from_file(vertices_back_csv_path, model, None)) except Exception: + logger.info( + "縲%s:%s縲題」上え繧ァ繧、繝育函謌", + param_option["material_name"], + param_option["abb_name"], + decoration=MLogger.DECORATION_LINE, + ) + logger.warning("陬城擇蟇セ雎。鬆らせCSV縺梧ュ」蟶ク縺ォ隱ュ縺ソ霎シ繧√↑縺九▲縺溘◆繧√∝ヲ逅繧偵せ繧ュ繝繝励@縺セ縺", decoration=MLogger.DECORATION_BOX) + # 谿九▲縺ヲ縺繧矩らせ + remaining_vidxs = dict([(vidx, rv) for rv in remaining_vertices.values() for vidx in rv.vidxs()]) + if not back_vertices: - return + return list(remaining_vidxs.keys()) # 驥崎、繧帝勁螟 back_vertices = list(set(back_vertices)) - logger.info("縲%s:%s縲題」上え繧ァ繧、繝育函謌", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) + logger.info( + "縲%s:%s縲題」上え繧ァ繧、繝育函謌", + param_option["material_name"], + param_option["abb_name"], + decoration=MLogger.DECORATION_LINE, + ) weight_cnt = 0 prev_weight_cnt = 0 - # 蝪励j邨ゅo縺」縺滄らせ縺ィ蜃ヲ逅蟇セ雎。譚占ウェ鬆らせ縺ョ隲也炊蜥碁らせ繝ェ繧ケ繝医r蟇セ雎。縺ィ縺吶k + # 蜃ヲ逅蟇セ雎。譚占ウェ鬆らせ縺九i谿矩らせ縺ィ陬城らせ繧貞シ輔>縺滄らせ繝ェ繧ケ繝医r陬上え繧ァ繧、繝医ョ蟇セ雎。縺ィ縺吶k front_vertices = {} - for vidx in list(set(weighted_vidxs) | (set(model.material_vertices[material_name]) - set(back_vertices))): + for vidx in list(set(target_vertices) - set(list(remaining_vidxs.keys())) - set(back_vertices)): v = model.vertex_dict[vidx] front_vertices[v.index] = v.position.data() + back_weighted_vidxs = [] for vertex_idx in back_vertices: bv = model.vertex_dict[vertex_idx] @@ -3221,6 +4159,8 @@ def create_back_weight( logger.debug(f"陬城らせ: back [{bv.index}], front [{copy_front_vertex_idx}], 霍晞屬 [{np.min(bv_distances)}]") bv.deform = copy.deepcopy(model.vertex_dict[copy_front_vertex_idx].deform) + back_weighted_vidxs.append(bv.index) + weight_cnt += 1 if weight_cnt > 0 and weight_cnt // 200 > prev_weight_cnt: logger.info("-- 陬城らせ繧ヲ繧ァ繧、繝: %s蛟狗岼:邨ゆコ", weight_cnt) @@ -3228,6 +4168,9 @@ def create_back_weight( logger.info("-- 陬城らせ繧ヲ繧ァ繧、繝: %s蛟狗岼:邨ゆコ", weight_cnt) + # 谿矩らせ縺九i蝪励j邨ゅo縺」縺溯」城らせ繧帝勁螟悶☆繧 + return list(set(list(remaining_vidxs.keys())) - set(back_weighted_vidxs)) + def create_remaining_weight( self, model: PmxModel, @@ -3236,26 +4179,26 @@ def create_remaining_weight( virtual_vertices: dict, vertex_maps: dict, all_regist_bones: dict, - remaining_vertices: dict, + remaining_vidxs: list, threshold: float, ): + if not remaining_vidxs: + return + logger.info("縲%s:%s縲第ョ九え繧ァ繧、繝育函謌", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) vertex_cnt = 0 prev_vertex_cnt = 0 - # 繧ヲ繧ァ繧、繝亥。励j邨ゅo縺」縺溷ョ滄らせ繝ェ繧ケ繝 - weighted_vidxs = [] - - # 蝪励j邨ゅo縺」縺滄らせ繝ェ繧ケ繝 - weighted_vkeys = list(set(list(virtual_vertices.keys())) - set(list(remaining_vertices.keys()))) - - weighted_poses = {} - for vkey in weighted_vkeys: - vv = virtual_vertices[vkey] - if vv.vidxs(): - weighted_poses[vkey] = vv.position().data() - weighted_vidxs.extend(vv.vidxs()) + # 繧ヲ繧ァ繧、繝亥。励j邨ゅo縺」縺溷ョ滄らせINDEX縺ィ縺昴ョ菴咲スョ + weighted_vidxs = dict( + [ + (vidx, model.vertex_dict[vidx].position.data()) + for vv in virtual_vertices.values() + for vidx in vv.vidxs() + if vidx not in remaining_vidxs + ] + ) # 逋サ骭イ貂医∩縺ョ繝懊シ繝ウ縺ョ菴咲スョ繝ェ繧ケ繝 bone_poses = {} @@ -3274,74 +4217,49 @@ def create_remaining_weight( bone_poses[bones[0].index] = bones[0].position.data() continue - # 繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺ェ縺邂謇縺九▽縺セ縺繧ヲ繧ァ繧、繝医′蝪励i繧後※縺ェ縺縺ョ縺ッ谿矩らせ縺ォ蜈・繧後k - if v_key not in remaining_vertices and not vv.deform: - remaining_vertices[v_key] = vv + # 縺セ縺繧ヲ繧ァ繧、繝医′蝪励i繧後※縺ェ縺縺ョ縺ッ谿矩らせ縺ォ蜈・繧後k + if not vv.deform: + remaining_vidxs.extend(vv.vidxs()) # 陬セ譚占ウェ繧定ソス蜉 if param_option["edge_material_name"] or param_option["edge_extend_material_names"]: for mname in [param_option["edge_material_name"]] + param_option["edge_extend_material_names"]: if not mname: continue - - for vidx in model.material_vertices[param_option["edge_material_name"]]: - v = model.vertex_dict[vidx] - v_key = v.position.to_key(threshold) - if v_key not in remaining_vertices: - remaining_vertices[v_key] = VirtualVertex(v_key) - vv.append([v], [], []) - remaining_vertices[v_key].append([v], [], []) + remaining_vidxs.extend(model.material_vertices[param_option["edge_material_name"]]) if param_option["vertices_edge_csv"]: try: for vertices_edge_csv_path in glob(param_option["vertices_edge_csv"]): - for vidx in read_vertices_from_file(vertices_edge_csv_path, model, None): - v = model.vertex_dict[vidx] - v_key = v.position.to_key(threshold) - if v_key not in remaining_vertices: - remaining_vertices[v_key] = VirtualVertex(v_key) - vv.append([v], [], []) - remaining_vertices[v_key].append([v], [], []) + remaining_vidxs.extend(read_vertices_from_file(vertices_edge_csv_path, model, None)) except Exception: logger.warning("陬セ蟇セ雎。鬆らせCSV縺梧ュ」蟶ク縺ォ隱ュ縺ソ霎シ繧√↑縺九▲縺溘◆繧√∝ヲ逅繧偵せ繧ュ繝繝励@縺セ縺", decoration=MLogger.DECORATION_BOX) - remain_cnt = len(remaining_vertices) * 2 - while remaining_vertices.items() and remain_cnt > 0: + # 驥崎、繧帝勁螟 + remaining_vidx_dicts = dict([(vidx, vidx) for vidx in list(set(remaining_vidxs))]) + + remain_cnt = len(remaining_vidx_dicts) * 2 + while remaining_vidx_dicts and remain_cnt > 0: remain_cnt -= 1 # 繝ゥ繝ウ繝繝縺ァ驕ク縺カ - vkey = list(remaining_vertices.keys())[random.randrange(len(remaining_vertices))] - vv = remaining_vertices[vkey] - - if not vv.vidxs(): - # vidx 縺後↑縺縺ョ縺ッ縺昴b縺昴b蟇セ雎。螟 - del remaining_vertices[vkey] - continue + vidx = list(remaining_vidx_dicts.keys())[random.randrange(len(remaining_vidx_dicts))] + rv = model.vertex_dict[vidx] # 繧ヲ繧ァ繧、繝域ク医∩鬆らせ縺ョ縺縺。縲∵怙繧りソ代>縺ョ繧呈歓蜃コ weighted_diff_distances = np.linalg.norm( - np.array(list(weighted_poses.values())) - vv.position().data(), ord=2, axis=1 + np.array(list(weighted_vidxs.values())) - rv.position.data(), ord=2, axis=1 ) - nearest_vkey = list(weighted_poses.keys())[np.argmin(weighted_diff_distances)] - nearest_vv = virtual_vertices[nearest_vkey] - nearest_deform = nearest_vv.deform - # nearest_vv.connected_vvs.extend(vv.vidxs()) - - if not nearest_vv.deform: - # 繝繝輔か繝シ繝縺ョ蟇セ雎。縺後↑縺蝣エ蜷医∽サ悶〒蝓九∪繧句庄閭ス諤ァ縺後≠繧九ョ縺ァ縲∽ク譌ヲ謐ョ縺育スョ縺 - continue + nearest_vidx = list(weighted_vidxs.keys())[np.argmin(weighted_diff_distances)] + nearest_deform = model.vertex_dict[nearest_vidx].deform if type(nearest_deform) is Bdef1: logger.debug( - f"remaining1 nearest_vv: {nearest_vv.vidxs()}, weight_names: [{model.bone_indexes[nearest_deform.index0]}], total_weights: [1]" + f"remaining1 nearest_vidx: {nearest_vidx}, weight_names: [{model.bone_indexes[nearest_deform.index0]}], total_weights: [1]" ) + rv.deform = Bdef1(nearest_deform.index0) - for rv in vv.real_vertices: - weighted_vidxs.append(rv.index) - rv.deform = Bdef1(nearest_deform.index0) - vv.deform = Bdef1(nearest_deform.index0) - - del remaining_vertices[vkey] + del remaining_vidx_dicts[vidx] elif type(nearest_deform) is Bdef2: weight_bone1 = model.bones[model.bone_indexes[nearest_deform.index0]] weight_bone2 = model.bones[model.bone_indexes[nearest_deform.index1]] @@ -3365,19 +4283,19 @@ def create_remaining_weight( weight_idxs = np.argsort(weights) logger.debug( - f"remaining2 nearest_vv: {vv.vidxs()}, weight_names: [{weight_names}], total_weights: [{total_weights}]" + f"remaining2 nearest_vidx: {nearest_vidx}, weight_names: [{weight_names}], total_weights: [{total_weights}]" ) if np.count_nonzero(weights) == 1: - vv.deform = Bdef1(model.bones[weight_names[weight_idxs[-1]]].index) + rv.deform = Bdef1(model.bones[weight_names[weight_idxs[-1]]].index) elif np.count_nonzero(weights) == 2: - vv.deform = Bdef2( + rv.deform = Bdef2( model.bones[weight_names[weight_idxs[-1]]].index, model.bones[weight_names[weight_idxs[-2]]].index, weights[weight_idxs[-1]], ) else: - vv.deform = Bdef4( + rv.deform = Bdef4( model.bones[weight_names[weight_idxs[-1]]].index, model.bones[weight_names[weight_idxs[-2]]].index, model.bones[weight_names[weight_idxs[-3]]].index, @@ -3388,11 +4306,7 @@ def create_remaining_weight( weights[weight_idxs[-4]], ) - for rv in vv.real_vertices: - weighted_vidxs.append(rv.index) - rv.deform = vv.deform - - del remaining_vertices[vkey] + del remaining_vidx_dicts[vidx] elif type(nearest_deform) is Bdef4: weight_bone1 = model.bones[model.bone_indexes[nearest_deform.index0]] weight_bone2 = model.bones[model.bone_indexes[nearest_deform.index1]] @@ -3430,19 +4344,19 @@ def create_remaining_weight( weight_idxs = np.argsort(weights) logger.debug( - f"remaining4 nearest_vv: {vv.vidxs()}, weight_names: [{weight_names}], total_weights: [{total_weights}]" + f"remaining4 nearest_vidx: {nearest_vidx}, weight_names: [{weight_names}], total_weights: [{total_weights}]" ) if np.count_nonzero(weights) == 1: - vv.deform = Bdef1(model.bones[weight_names[weight_idxs[-1]]].index) + rv.deform = Bdef1(model.bones[weight_names[weight_idxs[-1]]].index) elif np.count_nonzero(weights) == 2: - vv.deform = Bdef2( + rv.deform = Bdef2( model.bones[weight_names[weight_idxs[-1]]].index, model.bones[weight_names[weight_idxs[-2]]].index, weights[weight_idxs[-1]], ) else: - vv.deform = Bdef4( + rv.deform = Bdef4( model.bones[weight_names[weight_idxs[-1]]].index, model.bones[weight_names[weight_idxs[-2]]].index, model.bones[weight_names[weight_idxs[-3]]].index, @@ -3453,11 +4367,7 @@ def create_remaining_weight( weights[weight_idxs[-4]], ) - for rv in vv.real_vertices: - weighted_vidxs.append(rv.index) - rv.deform = vv.deform - - del remaining_vertices[vkey] + del remaining_vidx_dicts[vidx] vertex_cnt += 1 @@ -3467,8 +4377,6 @@ def create_remaining_weight( logger.info("-- 谿九え繧ァ繧、繝: %s蛟狗岼:邨ゆコ", vertex_cnt) - return weighted_vidxs - def create_weight( self, model: PmxModel, @@ -3508,6 +4416,9 @@ def create_weight( vkey = tuple(vertex_map[v_yidx, v_xidx]) vv = virtual_vertices[vkey] + if vv.deform: + continue + ( prev_map_idx, prev_xidx, @@ -3534,7 +4445,7 @@ def create_weight( [ mbone.index for mbone in virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].map_bones.values() - if mbone + if mbone and mbone.name in model.bones and mbone.getVisibleFlag() ] ) ) @@ -3582,9 +4493,76 @@ def create_weight( logger.debug(f"BDEF1 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 - if vkey in remaining_vertices: + if vv.real_vertices and vkey in remaining_vertices: del remaining_vertices[vkey] + elif np.where(regist_bones[:, v_xidx])[0].shape[0] > 1: + # 蜷後§X菴咲スョ縺ォ繝懊シ繝ウ縺後≠繧句エ蜷医∫クヲ縺ョBDEF2逋サ骭イ蟇セ雎。 + if ( + not all_bone_vertical_distances[base_map_idx].any() + or np.isnan(vertex_map[above_yidx, v_xidx]).any() + or np.isnan(vertex_map[below_yidx, v_xidx]).any() + or not virtual_vertices[tuple(vertex_map[above_yidx, v_xidx])].map_bones.get( + base_map_idx, None + ) + or not virtual_vertices[tuple(vertex_map[below_yidx, v_xidx])].map_bones.get( + base_map_idx, None + ) + ): + continue + + above_weight = np.nan_to_num( + np.sum(all_bone_vertical_distances[base_map_idx][(above_yidx + 1) : (v_yidx + 1), v_xidx]) + / np.sum( + all_bone_vertical_distances[base_map_idx][(above_yidx + 1) : (below_yidx + 1), v_xidx] + ) + ) + + weight_bone_idx_0 = ( + virtual_vertices[tuple(vertex_map[above_yidx, v_xidx])].map_bones[base_map_idx].index + ) + weight_bone_idx_1 = ( + virtual_vertices[tuple(vertex_map[below_yidx, v_xidx])].map_bones[base_map_idx].index + ) + + if ( + np.isclose(above_weight, 0) + and model.bones[model.bone_indexes[weight_bone_idx_0]].getVisibleFlag() + ): + vv.deform = Bdef1(weight_bone_idx_0) + elif ( + np.isclose(above_weight, 1) + and model.bones[model.bone_indexes[weight_bone_idx_1]].getVisibleFlag() + ): + vv.deform = Bdef1(weight_bone_idx_1) + elif ( + model.bones[model.bone_indexes[weight_bone_idx_0]].getVisibleFlag() + and model.bones[model.bone_indexes[weight_bone_idx_1]].getVisibleFlag() + ): + vv.deform = Bdef2( + weight_bone_idx_0, + weight_bone_idx_1, + 1 - above_weight, + ) + + if vv.deform: + for rv in vv.real_vertices: + rv.deform = vv.deform + + # 騾逋サ骭イ + if weight_bone_idx_0 not in model.vertices: + model.vertices[weight_bone_idx_0] = [] + model.vertices[weight_bone_idx_0].append(rv) + if weight_bone_idx_1 not in model.vertices: + model.vertices[weight_bone_idx_1] = [] + model.vertices[weight_bone_idx_1].append(rv) + + logger.debug(f"BDEF2 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vv.real_vertices and vkey in remaining_vertices: + del remaining_vertices[vkey] + elif np.where(regist_bones[v_yidx, :])[0].shape[0] > 1: # 蜷後§Y菴咲スョ縺ォ繝懊シ繝ウ縺後≠繧句エ蜷医∵ィェ縺ョBDEF2逋サ骭イ蟇セ雎。 if v_xidx < regist_bones.shape[1] - 1 and regist_bones[v_yidx, (v_xidx + 1) :].any(): @@ -3629,96 +4607,44 @@ def create_weight( .index ) - if np.isclose(prev_weight, 0): - vv.deform = Bdef1(weight_bone_idx_0) - elif np.isclose(prev_weight, 1): - vv.deform = Bdef1(weight_bone_idx_1) - else: - vv.deform = Bdef2( - weight_bone_idx_0, - weight_bone_idx_1, - 1 - prev_weight, - ) - - for rv in vv.real_vertices: - rv.deform = vv.deform - - # 騾逋サ骭イ - if weight_bone_idx_0 not in model.vertices: - model.vertices[weight_bone_idx_0] = [] - model.vertices[weight_bone_idx_0].append(rv) - if weight_bone_idx_1 not in model.vertices: - model.vertices[weight_bone_idx_1] = [] - model.vertices[weight_bone_idx_1].append(rv) - - logger.debug(f"BDEF2 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") - - # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 - if vkey in remaining_vertices: - del remaining_vertices[vkey] - - elif np.where(regist_bones[:, v_xidx])[0].shape[0] > 1: - # 蜷後§X菴咲スョ縺ォ繝懊シ繝ウ縺後≠繧句エ蜷医∫クヲ縺ョBDEF2逋サ骭イ蟇セ雎。 if ( - not all_bone_vertical_distances[base_map_idx].any() - or np.isnan(vertex_map[above_yidx, v_xidx]).any() - or np.isnan(vertex_map[below_yidx, v_xidx]).any() - or not virtual_vertices[tuple(vertex_map[above_yidx, v_xidx])].map_bones.get( - base_map_idx, None - ) - or not virtual_vertices[tuple(vertex_map[below_yidx, v_xidx])].map_bones.get( - base_map_idx, None - ) + np.isclose(prev_weight, 0) + and model.bones[model.bone_indexes[weight_bone_idx_0]].getVisibleFlag() ): - continue - - above_weight = np.nan_to_num( - np.sum( - all_bone_vertical_distances[base_map_idx][ - (above_yidx + 1) : (v_yidx + 1), (v_xidx - 1) - ] - ) - / np.sum( - all_bone_vertical_distances[base_map_idx][ - (above_yidx + 1) : (below_yidx + 1), (v_xidx - 1) - ] - ) - ) - - weight_bone_idx_0 = ( - virtual_vertices[tuple(vertex_map[above_yidx, v_xidx])].map_bones[base_map_idx].index - ) - weight_bone_idx_1 = ( - virtual_vertices[tuple(vertex_map[below_yidx, v_xidx])].map_bones[base_map_idx].index - ) - - if np.isclose(above_weight, 0): vv.deform = Bdef1(weight_bone_idx_0) - elif np.isclose(above_weight, 1): + elif ( + np.isclose(prev_weight, 1) + and model.bones[model.bone_indexes[weight_bone_idx_1]].getVisibleFlag() + ): vv.deform = Bdef1(weight_bone_idx_1) - else: + elif ( + model.bones[model.bone_indexes[weight_bone_idx_0]].getVisibleFlag() + and model.bones[model.bone_indexes[weight_bone_idx_1]].getVisibleFlag() + ): vv.deform = Bdef2( weight_bone_idx_0, weight_bone_idx_1, - 1 - above_weight, + 1 - prev_weight, ) - for rv in vv.real_vertices: - rv.deform = vv.deform + if vv.deform: + for rv in vv.real_vertices: + rv.deform = vv.deform - # 騾逋サ骭イ - if weight_bone_idx_0 not in model.vertices: - model.vertices[weight_bone_idx_0] = [] - model.vertices[weight_bone_idx_0].append(rv) - if weight_bone_idx_1 not in model.vertices: - model.vertices[weight_bone_idx_1] = [] - model.vertices[weight_bone_idx_1].append(rv) + # 騾逋サ骭イ + if weight_bone_idx_0 not in model.vertices: + model.vertices[weight_bone_idx_0] = [] + model.vertices[weight_bone_idx_0].append(rv) + if weight_bone_idx_1 not in model.vertices: + model.vertices[weight_bone_idx_1] = [] + model.vertices[weight_bone_idx_1].append(rv) - logger.debug(f"BDEF2 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") + logger.debug(f"BDEF2 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") + + # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 + if vv.real_vertices and vkey in remaining_vertices: + del remaining_vertices[vkey] - # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 - if vkey in remaining_vertices: - del remaining_vertices[vkey] else: if next_connected and next_xidx == 0: # 譛蠕後ョ鬆らせ縺ョ蝣エ蜷医√→繧翫≠縺医★谺。縺ョ霍晞屬繧貞ッセ雎。縺ィ縺吶k @@ -3759,10 +4685,8 @@ def create_weight( prev_above_weight = np.nan_to_num( ( - np.sum(all_bone_vertical_distances[base_map_idx][v_yidx:below_yidx, (v_xidx - 1)]) - / np.sum( - all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, (v_xidx - 1)] - ) + np.sum(all_bone_vertical_distances[base_map_idx][v_yidx:below_yidx, v_xidx]) + / np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, v_xidx]) ) * ( np.sum(all_bone_horizonal_distances[base_map_idx][v_yidx, v_xidx:next_xidx]) @@ -3772,10 +4696,8 @@ def create_weight( next_above_weight = np.nan_to_num( ( - np.sum(all_bone_vertical_distances[base_map_idx][v_yidx:below_yidx, (v_xidx - 1)]) - / np.sum( - all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, (v_xidx - 1)] - ) + np.sum(all_bone_vertical_distances[base_map_idx][v_yidx:below_yidx, v_xidx]) + / np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, v_xidx]) ) * ( np.sum(all_bone_horizonal_distances[base_map_idx][v_yidx, prev_xidx:v_xidx]) @@ -3785,10 +4707,8 @@ def create_weight( prev_below_weight = np.nan_to_num( ( - np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:v_yidx, (v_xidx - 1)]) - / np.sum( - all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, (v_xidx - 1)] - ) + np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:v_yidx, v_xidx]) + / np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, v_xidx]) ) * ( np.sum(all_bone_horizonal_distances[base_map_idx][v_yidx, v_xidx:next_xidx]) @@ -3798,10 +4718,8 @@ def create_weight( next_below_weight = np.nan_to_num( ( - np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:v_yidx, (v_xidx - 1)]) - / np.sum( - all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, (v_xidx - 1)] - ) + np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:v_yidx, v_xidx]) + / np.sum(all_bone_vertical_distances[base_map_idx][above_yidx:below_yidx, v_xidx]) ) * ( np.sum(all_bone_horizonal_distances[base_map_idx][v_yidx, prev_xidx:v_xidx]) @@ -3870,7 +4788,7 @@ def create_weight( logger.debug(f"BDEF4 vkey[{vkey}], vidxs[{vv.vidxs()}], deform[{vv.deform}]") # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医∵ョ句ッセ雎。縺九i蜑企勁 - if vkey in remaining_vertices: + if vv.real_vertices and vkey in remaining_vertices: del remaining_vertices[vkey] weight_cnt += len(vv.real_vertices) @@ -3882,7 +4800,14 @@ def create_weight( return remaining_vertices - def create_root_bone(self, model: PmxModel, param_option: dict, material_name: str, root_pos: MVector3D): + def create_root_bone( + self, + model: PmxModel, + param_option: dict, + material_name: str, + root_pos: MVector3D, + base_vertical_axis: MVector3D, + ): # 逡・遘ー abb_name = param_option["abb_name"] # 陦ィ遉コ譫蜷 @@ -3904,12 +4829,10 @@ def create_root_bone(self, model: PmxModel, param_option: dict, material_name: s root_bone.name += randomname(3) root_bone.index = len(model.bones) - model.bones[root_bone.name] = root_bone - model.bone_indexes[root_bone.index] = root_bone.name + root_bone.tail_position = base_vertical_axis * 2 # 陦ィ遉コ譫 model.display_slots[display_name] = DisplaySlot(display_name, display_name, 0, 0) - model.display_slots[display_name].references.append((0, model.bones[root_bone.name].index)) return display_name, root_bone @@ -3922,6 +4845,7 @@ def create_bone( vertex_maps: dict, vertex_map_orders: dict, threshold: float, + base_vertical_axis: MVector3D, ): logger.info("縲%s:%s縲代懊シ繝ウ逕滓", material_name, param_option["abb_name"], decoration=MLogger.DECORATION_LINE) @@ -3936,9 +4860,13 @@ def create_bone( # 荳ュ蠢繝懊シ繝ウ display_name, root_bone = self.create_root_bone( - model, param_option, material_name, parent_bone.position.copy() + model, param_option, material_name, parent_bone.position.copy(), base_vertical_axis ) + tmp_all_bones = {root_bone.name: root_bone} + tmp_all_bone_indexes = {root_bone.index: root_bone.name} + tmp_all_bone_vvs = {} + logger.info("縲%s縲鷹らせ霍晞屬縺ョ邂怜コ", material_name) all_bone_horizonal_distances = {} @@ -3957,20 +4885,23 @@ def create_bone( # 蜷鬆らせ縺ョ霍晞屬シ亥蜻ィ縺」縺ス縺蜿ッ閭ス諤ァ縺後≠繧九◆繧√鬆らせ荳蛟九★縺、縺ァ貂ャ繧具シ for v_yidx in range(vertex_map.shape[0]): - v_xidx = -1 - for v_xidx in range(0, vertex_map.shape[1] - 1): + # 荳蛻励@縺九↑縺蝣エ蜷医ッ邵ヲ譁ケ蜷代r險医l繧九h縺縺ォ繧ェ繝輔そ繝繝医rOFF縺ォ縺吶k + x_end_offset = 1 if vertex_map.shape[1] > 1 else 0 + for v_xidx in range(0, vertex_map.shape[1] - x_end_offset): if ( - not np.isnan(vertex_map[v_yidx, v_xidx]).any() + v_xidx < vertex_map.shape[1] - 1 + and not np.isnan(vertex_map[v_yidx, v_xidx]).any() and not np.isnan(vertex_map[v_yidx, v_xidx + 1]).any() ): now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() next_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx + 1])].position() bone_horizonal_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(next_v_vec) - if tuple(vertex_map[v_yidx, v_xidx]) in virtual_vertices[ - tuple(vertex_map[v_yidx, v_xidx + 1]) - ].connected_vvs or tuple(vertex_map[v_yidx, v_xidx]) == tuple(vertex_map[v_yidx, v_xidx + 1]): - # 蜑阪ョ莉ョ諠ウ鬆らせ縺ィ蜷後§縺狗ケ九′縺」縺ヲ縺繧句エ蜷医ゝrue + if ( + tuple(vertex_map[v_yidx, v_xidx]) + in virtual_vertices[tuple(vertex_map[v_yidx, v_xidx + 1])].connected_vvs + ): + # 蜑阪ョ莉ョ諠ウ鬆らせ縺ィ郢九′縺」縺ヲ縺繧句エ蜷医ゝrue bone_connected[v_yidx, v_xidx] = True if ( @@ -3987,31 +4918,48 @@ def create_bone( logger.info("-- --縲侵o.%s縲鷹らせ霍晞屬邂怜コ: %s蛟狗岼:邨ゆコ", base_map_idx + 1, vertex_cnt) prev_vertex_cnt = vertex_cnt // 1000 - v_xidx += 1 - if ( - not np.isnan(vertex_map[v_yidx, v_xidx]).any() - and not np.isnan(vertex_map[v_yidx, 0]).any() - and vertex_map.shape[1] > 2 - ): + if v_xidx > 0: + v_xidx += 1 + # 譛邨り。後ョ邵ヲ霍晞屬縺ッ蜑埼らせ縺ョ霍晞屬繧呈オ∫畑 + bone_vertical_distances[v_yidx, v_xidx] = float(bone_vertical_distances[v_yidx, v_xidx - 1]) + if not np.isnan(vertex_map[v_yidx, v_xidx]).any(): # 霈ェ繧呈緒縺縺溘ョ繧ょ・繧後→縺(繧ヲ繧ァ繧、繝亥ッセ雎。蜿門セ励ョ譎ゅ↓遽蝗イ謖螳壼・繧九°繧峨%縺薙〒縺ッ蠑キ蛻カ) + next_base_map_idx = base_map_idx + 1 if base_map_idx + 1 in vertex_maps else 0 if ( - tuple(vertex_map[v_yidx, 0]) + vertex_maps[next_base_map_idx].shape[0] > v_yidx + and tuple(vertex_maps[next_base_map_idx][v_yidx, 0]) in virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].connected_vvs ): # 讓ェ縺ョ莉ョ諠ウ鬆らせ縺ィ郢九′縺」縺ヲ縺繧句エ蜷医ゝrue縺ァ譛牙柑縺ェ霍晞屬繧貞・繧後※縺翫¥ bone_connected[v_yidx, v_xidx] = True now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() - next_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, 0])].position() + next_v_vec = virtual_vertices[tuple(vertex_maps[next_base_map_idx][v_yidx, 0])].position() bone_horizonal_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(next_v_vec) else: # 縺ィ繧翫≠縺医★INT譛螟ァ蛟、繧貞・繧後※縺翫¥ bone_horizonal_distances[v_yidx, v_xidx] = np.iinfo(np.int).max + # elif base_map_idx > 0 and vertex_map.shape[1] == 1: + # # 荳蛻励ョ蝣エ蜷医∝燕縺ィ縺ョ郢九′繧翫r隕九※縺翫¥ + # if tuple(vertex_map[v_yidx, 0]) in virtual_vertices[ + # tuple(vertex_maps[base_map_idx - 1][v_yidx, -1]) + # ].connected_vvs or tuple(vertex_map[v_yidx, 0]) == tuple( + # vertex_maps[base_map_idx - 1][v_yidx, -1] + # ): + # # 讓ェ縺ョ莉ョ諠ウ鬆らせ縺ィ郢九′縺」縺ヲ縺繧句エ蜷医ゝrue縺ァ譛牙柑縺ェ霍晞屬繧貞・繧後※縺翫¥ + # bone_connected[v_yidx, v_xidx] = True + + # now_v_vec = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])].position() + # prev_v_vec = virtual_vertices[tuple(vertex_maps[base_map_idx - 1][v_yidx, -1])].position() + # bone_horizonal_distances[v_yidx, v_xidx] = now_v_vec.distanceToPoint(prev_v_vec) + # else: + # # 縺ィ繧翫≠縺医★INT譛螟ァ蛟、繧貞・繧後※縺翫¥ + # bone_horizonal_distances[v_yidx, v_xidx] = np.iinfo(np.int).max logger.debug("bone_horizonal_distances ------------") - logger.debug(bone_horizonal_distances.tolist()) + logger.debug(np.round(bone_horizonal_distances, decimals=3).tolist()) logger.debug("bone_vertical_distances ------------") - logger.debug(bone_vertical_distances.tolist()) + logger.debug(np.round(bone_vertical_distances, decimals=3).tolist()) logger.debug("bone_connected ------------") logger.debug(bone_connected.tolist()) @@ -4034,16 +4982,44 @@ def create_bone( and ( tuple(next_vertex_map[v_yidx, 0]) in virtual_vertices[tuple(vertex_map[v_yidx, -1])].connected_vvs - or tuple(vertex_map[v_yidx, -1]) == tuple(next_vertex_map[v_yidx, 0]) ) ): - # 蜷後§莉ョ諠ウ鬆らせ繧ゅ@縺上ッ郢九′繧後◆莉ョ諠ウ鬆らせ縺ョ蝣エ蜷医∫ケ九′繧後※縺繧九→縺ソ縺ェ縺 + # 郢九′繧後◆莉ョ諠ウ鬆らせ縺ョ蝣エ蜷医∫ケ九′繧後※縺繧九→縺ソ縺ェ縺 all_bone_connected[base_map_idx][v_yidx, -1] = True # 蜈ィ菴馴壹@縺ヲ縺ョX逡ェ蜿キ prev_xs = [] all_regist_bones = {} - tmp_all_bones = {} + all_y_bone_registers = [] + + for base_map_idx, vertex_map in vertex_maps.items(): + # Y霆ク縺ッ蜈ィ菴薙r騾壹@縺ヲ蜷後§邂謇縺ォ繝懊シ繝ウ繧貞シオ繧九◆繧√∽ク翫→郢九′縺」縺ヲ縺縺ェ縺邂謇縺ョ繝斐ャ繧ッ繧「繝繝 + y_diffs = np.diff(all_bone_connected[base_map_idx], axis=0) + y_diff_xs = np.argmin(y_diffs, axis=0) | np.argmax(y_diffs, axis=0) + y_diff_xs_prev = [] + if len(vertex_maps) > 1: + if base_map_idx == 0: + if set(np.unique(all_bone_connected[list(vertex_maps.keys())[1]][:, -1]).tolist()) == {0, 1}: + # 譛蠕後ョ繝槭ャ繝励→譛蛻昴ョ繝槭ャ繝励′郢九′縺」縺ヲ繧狗ョ謇縺ィ郢九′縺」縺ヲ縺ェ縺邂謇縺後≠繧句エ蜷 + y_diff_xs_prev.append(np.max(np.where(all_bone_connected[list(vertex_maps.keys())[1]][:, -1]))) + else: + if set(np.unique(all_bone_connected[base_map_idx - 1][:, -1]).tolist()) == {0, 1}: + # 迴セ蝨ィ縺ョ繝槭ャ繝励→蜑阪ョ繝槭ャ繝励′郢九′縺」縺ヲ繧狗ョ謇縺ィ郢九′縺」縺ヲ縺ェ縺邂謇縺後≠繧句エ蜷 + y_diff_xs_prev.append(np.max(np.where(all_bone_connected[base_map_idx - 1][:, -1]))) + + logger.debug( + "[%s] y_diff_xs_prev: %s", base_map_idx, sorted(list(set(np.where(y_diff_xs_prev)[0].tolist()))) + ) + logger.debug( + "[%s] y_diff_xs: %s", base_map_idx, sorted(list(set(y_diff_xs[np.where(np.diff(y_diff_xs))].tolist()))) + ) + + all_y_bone_registers.extend(y_diff_xs_prev) + all_y_bone_registers.extend(y_diff_xs[np.where(np.diff(y_diff_xs))].tolist()) + + logger.debug("all_y_bone_registers ------------") + logger.debug(sorted(list(set(np.where(all_y_bone_registers)[0].tolist())))) + for base_map_idx, vertex_map in vertex_maps.items(): prev_bone_cnt = 0 @@ -4053,82 +5029,14 @@ def create_bone( # 繝懊シ繝ウ逕滓仙ッセ雎。螟悶ョ蝣エ蜷医√せ繝ォ繝シ continue - # 繝懊シ繝ウ逋サ骭イ譛臥┌ + # 蜈ィ繝懊シ繝ウ逋サ骭イ譛臥┌ + full_regist_bones = np.zeros((vertex_map.shape[0], vertex_map.shape[1]), dtype=np.int) + # 螳滄圀縺ョ繝懊シ繝ウ逋サ骭イ譛臥┌ regist_bones = np.zeros((vertex_map.shape[0], vertex_map.shape[1]), dtype=np.int) - all_regist_bones[base_map_idx] = regist_bones logger.info("--縲侵o.%s縲代懊シ繝ウ逕滓", base_map_idx + 1) - if param_option["density_type"] == logger.transtext("霍晞屬"): - median_vertical_distance = ( - np.median(all_bone_vertical_distances[base_map_idx][:, int(vertex_map.shape[1] / 2)]) * 0.9 - ) - median_horizonal_distance = ( - np.median(all_bone_horizonal_distances[base_map_idx][int(vertex_map.shape[0] / 2), :]) * 0.9 - ) - - logger.debug( - f"median_horizonal_distance: {round(median_horizonal_distance, 4)}, median_vertical_distance: {round(median_vertical_distance, 4)}" - ) - - # 髢馴囈縺瑚キ晞屬繧ソ繧、繝励ョ蝣エ蜷医∝插遲峨↓縺ェ繧九h縺縺ォ髢薙r遨コ縺代k - y_regists = np.zeros(vertex_map.shape[0], dtype=np.int) - prev_y_regist = 0 - for v_yidx in range(vertex_map.shape[0]): - if ( - np.sum( - all_bone_vertical_distances[base_map_idx][ - (prev_y_regist + 1) : (v_yidx + 1), int(vertex_map.shape[1] / 2) - ] - ) - > median_vertical_distance * param_option["vertical_bone_density"] - ): - # 蜑阪ョ逋サ骭イ繝懊シ繝ウ縺九i荳螳夊キ晞屬髮「繧後◆繧臥匳骭イ蟇セ雎。 - y_regists[v_yidx] = True - prev_y_regist = v_yidx - # 譛蛻昴→譛蠕後ッ蠢縺夂匳骭イ縺吶k - y_regists[0] = y_regists[-1] = True - - x_regists = np.zeros(vertex_map.shape[1], dtype=np.int) - prev_x_regist = 0 - for v_xidx in range(vertex_map.shape[1]): - if ( - np.sum( - all_bone_horizonal_distances[base_map_idx][ - int(vertex_map.shape[0] / 2), (prev_x_regist + 1) : (v_xidx + 1) - ] - ) - > median_horizonal_distance * param_option["horizonal_bone_density"] - ): - # 蜑阪ョ逋サ骭イ繝懊シ繝ウ縺九i荳螳夊キ晞屬髮「繧後◆繧臥匳骭イ蟇セ雎。 - x_regists[v_xidx] = True - prev_x_regist = v_xidx - # 譛蛻昴→譛蠕後ッ蠢縺夂匳骭イ縺吶k - x_regists[0] = x_regists[-1] = True - - for v_yidx, y_regist in enumerate(y_regists): - for v_xidx, x_regist in enumerate(x_regists): - regist_bones[v_yidx, v_xidx] = y_regist and x_regist - - elif param_option["density_type"] == logger.transtext("鬆らせ"): - # 髢馴囈縺碁らせ繧ソ繧、繝励ョ蝣エ蜷医∬ヲ丞援逧縺ォ髢薙r遨コ縺代k(Y縺ッ譛ォ遶ッ縺ッ髱櫁。ィ遉コ縺ォ縺ェ繧九ョ縺ァ縲√b縺荳縺、荳翫b逋サ骭イ蟇セ雎。) - for v_yidx in list(range(0, vertex_map.shape[0], param_option["vertical_bone_density"])) + [ - vertex_map.shape[0] - 2, - vertex_map.shape[0] - 1, - ]: - for v_xidx in list(range(0, vertex_map.shape[1], param_option["horizonal_bone_density"])) + [ - vertex_map.shape[1] - 1 - ]: - if not np.isnan(vertex_map[v_yidx, v_xidx]).any() and ( - v_xidx <= vertex_map.shape[1] - param_option["horizonal_bone_density"] - or not all_bone_connected[base_map_idx][v_yidx, v_xidx] - ): - regist_bones[v_yidx, v_xidx] = True - - if vertex_map.shape[0] - 2 <= v_yidx and not regist_bones[:v_yidx, v_xidx].any(): - # 莉ョ諠ウ繝懊シ繝ウシ区忰遶ッ縺ッ縺昴l繧医j荳翫′郢九′縺」縺ヲ縺溘i逋サ骭イ縺励↑縺 - regist_bones[v_yidx, v_xidx] = False - else: + if param_option["density_type"] == logger.transtext("荳ュ螟ョ"): # 髢馴囈縺後そ繝ウ繧ソ繝シ繧ソ繧、繝励ョ蝣エ蜷医∫悄繧謎クュ縺ォ縺ョ縺ソ繝懊シ繝ウ繧貞シオ繧 # 譛ォ遶ッ縺ッ髱櫁。ィ遉コ縺ァ逋サ骭イ縺吶k for v_yidx in list(range(0, vertex_map.shape[0], param_option["vertical_bone_density"])) + [ @@ -4138,6 +5046,221 @@ def create_bone( v_xidx = (vertex_map.shape[1] // 2) - (1 - vertex_map.shape[1] % 2) if not np.isnan(vertex_map[v_yidx, v_xidx]).any(): regist_bones[v_yidx, v_xidx] = True + else: + # 繝懊シ繝ウ縺檎ケ九′縺」縺ヲ繧九ヨ繧ウ繝ュ縺檎函謌千ッ蝗イ + full_regist_bones = all_bone_connected[base_map_idx].copy() + # # 蜈磯ュ縺ッ譛蛻昴ョ繧偵さ繝斐シ + # full_regist_bones[:, -1] = full_regist_bones[:, -2].copy() + # 繝励Λ繧ケ縺ョ蝣エ蜷医∝燕縺ィ郢九′縺」縺ヲ縺縺ェ縺縺ョ縺ァ逋サ骭イ蟇セ雎。 + full_regist_bones[:, 1:][np.where(np.diff(all_bone_connected[base_map_idx], axis=1) < 0)] = True + + y_registers = np.zeros(vertex_map.shape[0], dtype=np.int) + x_registers = np.zeros(vertex_map.shape[1], dtype=np.int) + + if param_option["density_type"] == logger.transtext("霍晞屬"): + median_vertical_distance = ( + np.median(all_bone_vertical_distances[base_map_idx][:, int(vertex_map.shape[1] / 2)]) * 0.9 + ) + median_horizonal_distance = ( + np.median(all_bone_horizonal_distances[base_map_idx][int(vertex_map.shape[0] / 2), :]) * 0.9 + ) + + logger.debug( + f"median_horizonal_distance: {round(median_horizonal_distance, 4)}, median_vertical_distance: {round(median_vertical_distance, 4)}" + ) + + # 髢馴囈縺瑚キ晞屬繧ソ繧、繝励ョ蝣エ蜷医∝插遲峨↓縺ェ繧九h縺縺ォ髢薙r遨コ縺代k + prev_y_regist = 0 + for v_yidx in range(vertex_map.shape[0]): + if ( + np.sum( + all_bone_vertical_distances[base_map_idx][ + (prev_y_regist + 1) : (v_yidx + 1), int(vertex_map.shape[1] / 2) + ] + ) + > median_vertical_distance * param_option["vertical_bone_density"] + ): + # 蜑阪ョ逋サ骭イ繝懊シ繝ウ縺九i荳螳夊キ晞屬髮「繧後◆繧臥匳骭イ蟇セ雎。 + y_registers[v_yidx] = True + prev_y_regist = v_yidx + + prev_x_regist = 0 + for v_xidx in range(vertex_map.shape[1]): + if ( + np.sum( + all_bone_horizonal_distances[base_map_idx][ + int(vertex_map.shape[0] / 2), (prev_x_regist + 1) : (v_xidx + 1) + ] + ) + > median_horizonal_distance * param_option["horizonal_bone_density"] + ): + # 蜑阪ョ逋サ骭イ繝懊シ繝ウ縺九i荳螳夊キ晞屬髮「繧後◆繧臥匳骭イ蟇セ雎。 + x_registers[v_xidx] = True + prev_x_regist = v_xidx + + elif param_option["density_type"] == logger.transtext("鬆らせ"): + y_registers = ( + np.array(list(range(vertex_map.shape[0]))) % param_option["vertical_bone_density"] == 0 + ) + x_registers = ( + np.array(list(range(vertex_map.shape[1]))) % param_option["horizonal_bone_density"] == 0 + ) + + # 譛蛻昴ッ蠢縺夂匳骭イ縺吶k + y_registers[0] = True + x_registers[0] = True + if np.where(all_bone_connected[base_map_idx][:-1, -1] == 0)[0].any(): + # X譁ケ蜷代ョ譛ォ遶ッ縺後←縺薙°郢九′縺」縺ヲ辟。縺縺ィ縺薙′縺ゅ▲縺溘i譛ォ遶ッ縺ォ繝懊シ繝ウ繧貞シオ繧 + x_registers[-1] = True + + logger.debug("[%s] x_registers: %s", base_map_idx, x_registers) + logger.debug("[%s] y_registers: %s", base_map_idx, y_registers) + + # 蜑阪→郢九′縺」縺ヲ縺縺ェ縺邂謇縺ョ繝斐ャ繧ッ繧「繝繝 + x_diffs = np.diff(all_bone_connected[base_map_idx], axis=1) + x_bone_registers = sorted( + list( + set(np.where(x_registers)[0].tolist()) + | set((np.where(x_diffs == 1)[1] + 1).tolist()) + | set((np.where(x_diffs == -1)[1] + 1).tolist()) + ) + ) + logger.debug("[%s] x_bone_registers: %s", base_map_idx, x_bone_registers) + + # Y霆ク縺ッ蜈ィ菴薙r騾壹@縺ヲ繝懊シ繝ウ繧貞シオ繧九∋縺咲ョ謇シ玖ェ霄ォ縺ョ逋サ骭イ蟇セ雎。菴咲スョ繧堤匳骭イ蟇セ雎。縺ィ縺吶k + y_bone_registers = sorted(list(set(np.where(y_registers)[0].tolist()) | set(all_y_bone_registers))) + logger.debug("[%s] y_bone_registers: %s", base_map_idx, y_bone_registers) + + # XY霆ク縺ァ繝懊シ繝ウ繧堤匳骭イ縺吶k + # 荳譌ヲ螳滄圀縺ォ鬆らせ縺後≠繧九→縺薙m縺ョ縺ソ蟇セ雎。縺ィ縺吶k + registered_idxs = np.array( + [ + np.array([y, x]) + for y in y_bone_registers + for x in x_bone_registers + if y < vertex_map.shape[0] + and x < vertex_map.shape[1] + and not np.isnan(vertex_map[y, x]).any() + and virtual_vertices[tuple(vertex_map[y, x])].vidxs() + ] + ) + regist_bones[registered_idxs[:, 0], registered_idxs[:, 1]] = True + + # if base_map_idx > 0 and not x_diffs[0].any(): + # min_y = min( + # all_bone_connected[base_map_idx].shape[0], all_bone_connected[base_map_idx - 1].shape[0] + # ) + # x_diffs = np.where( + # ( + # all_bone_connected[base_map_idx][:min_y, :1] + # - all_bone_connected[base_map_idx - 1][:min_y, -1:] + # ) + # < 0 + # ) + # if x_diffs[0].any(): + # not_connected_xs = [(yi, xi + 1) for yi, xi in zip(x_diffs[0], x_diffs[1] + 1)] + # else: + # not_connected_xs = [] + + # y_diffs = np.where(np.diff(all_bone_connected[base_map_idx][:-1, :], axis=0) < 0) + # if y_diffs[0].any(): + # not_connected_ys = [(yi, xi) for yi, xi in zip(y_diffs[0], y_diffs[1])] + # else: + # not_connected_ys = [] + + # for v_yidx, y_regist in enumerate(y_registers): + # for v_xidx, x_regist in enumerate(x_registers): + # # XY縺ョ荳。譁ケ縺瑚キ晞屬譚。莉カ繧呈コ縺溘@縺ヲ縺縺ヲ縲√°縺、繝懊シ繝ウ縺悟シオ繧後k迥カ諷九↑繧臥匳骭イ蟇セ雎。 + # if full_regist_bones[v_yidx, v_xidx] and ( + # (y_regist and x_regist) + # or ( + # not y_regist + # and x_regist + # and full_regist_bones[max(0, v_yidx - 1), v_xidx] == 1 + # and full_regist_bones[min(vertex_map.shape[0] - 1, v_yidx + 1), v_xidx] == 0 + # ) + # or ( + # not x_regist + # and y_regist + # and ( + # ( + # full_regist_bones[v_yidx, max(0, v_xidx - 1)] == 1 + # and full_regist_bones[v_yidx, min(vertex_map.shape[1] - 1, v_xidx + 1)] == 0 + # ) + # or ( + # full_regist_bones[v_yidx, max(0, v_xidx - 1)] == 0 + # and full_regist_bones[v_yidx, min(vertex_map.shape[1] - 1, v_xidx + 1)] == 1 + # ) + # ) + # ) + # # or len( + # # np.where( + # # full_regist_bones[ + # # max(0, v_yidx - 1) : min(v_yidx + 2, vertex_map.shape[0]), + # # max(0, v_xidx - 1) : min(v_xidx + 2, vertex_map.shape[1]), + # # ] + # # == 0 + # # )[0] + # # ) + # or (v_yidx, v_xidx) in not_connected_xs + # or (v_yidx, v_xidx) in not_connected_ys + # ): + # regist_bones[v_yidx, v_xidx] = True + + for v_xidx in range(vertex_map.shape[1]): + # 譛ォ遶ッ繝懊シ繝ウ繧定ソス蜉逋サ骭イ + x_registered = np.where(regist_bones[:, v_xidx])[0] + if x_registered.any(): + # first_connected_v_yidx = np.min(x_registered) + # 譛ォ遶ッ縺ッ讓ェ縺ィ郢九′縺」縺ヲ縺ェ縺蝣エ蜷医b縺ゅk縺ョ縺ァ蜈ィ菴薙°繧芽ヲ九k + last_connected_v_yidx = max( + [ + y + for y in range(vertex_map.shape[0]) + if virtual_vertices[tuple(vertex_map[y, v_xidx])].vidxs() + ] + ) + # if first_connected_v_yidx == last_connected_v_yidx: + # # 荳蛻励↓縺イ縺ィ縺、縺励°逋サ骭イ縺輔l縺ヲ縺ェ縺蝣エ蜷医∽ク崎ヲ√↑縺ョ縺ァ蜑企勁 + # regist_bones[ + # min(last_connected_v_yidx, vertex_map.shape[0] - 1), + # v_xidx, + # ] = False + # else: + # for v_yidx in range(vertex_map.shape[0]): + # if y_registers[v_yidx] and v_yidx <= last_connected_v_yidx: + # regist_bones[v_yidx, v_xidx] = True + + # 譛ォ遶ッ繝懊シ繝ウ霑ス蜉逋サ骭イ + regist_bones[ + last_connected_v_yidx : min(last_connected_v_yidx + 2, vertex_map.shape[0]), + v_xidx, + ] = True + + if len(vertex_maps) > 1 and base_map_idx == 0: + # 譛蛻昴ョ蝣エ蜷医∵怙蠕後→郢九′縺」縺ヲ縺繧九ヨ繧ウ繝ュ繧偵メ繧ァ繝繧ッ縺吶k + next_x_registered = np.where(all_bone_connected[len(all_bone_connected) - 1][:, -1])[0] + if next_x_registered.any(): + next_last_connected_v_yidx = np.max(next_x_registered) + regist_bones[ + next_last_connected_v_yidx : min(next_last_connected_v_yidx + 1, vertex_map.shape[0] - 1), + 0, + ] = True + elif base_map_idx > 0: + # 2譫夂岼莉・髯阪ョ蝣エ蜷医∝燕縺ィ郢九′縺」縺ヲ繧区怙蠕後ョ繝医さ繝ュ縺ォ縺ッ繝懊シ繝ウ繧貞シオ繧 + prev_x_registered = np.where(all_bone_connected[base_map_idx - 1][:, -1])[0] + if prev_x_registered.any(): + prev_last_connected_v_yidx = np.max(prev_x_registered) + regist_bones[ + prev_last_connected_v_yidx : min(prev_last_connected_v_yidx + 1, vertex_map.shape[0] - 1), + 0, + ] = True + + # for v_yidx in np.where(np.sum(regist_bones, axis=1))[0]: + # # 讓ェ譁ケ蜷代ョ繝懊シ繝ウ逋サ骭イ縺悟ソ隕√↑縺ョ縺ァX逋サ骭イ蟇セ雎。繝懊シ繝ウ縺セ縺ァ縺ョ霑ス蜉逋サ骭イ + # regist_bones[v_yidx, np.where(x_registers & full_regist_bones[v_yidx, :])] = True + + all_regist_bones[base_map_idx] = regist_bones for v_yidx in range(vertex_map.shape[0]): for v_xidx in range(vertex_map.shape[1]): @@ -4163,6 +5286,8 @@ def create_bone( # 逋サ骭イ縺輔l縺ヲ縺縺溘i邨ゆコ break + # is_regist = True + # substitute_bone = None if not parent_bone: if v_yidx > 0: # 0逡ェ逶ョ莉・髯阪ッ譌「縺ォ逋サ骭イ貂医∩縺ョ荳翫ョ繝懊シ繝ウ繧呈治逕ィ縺吶k @@ -4197,12 +5322,10 @@ def create_bone( if not vv.map_bones.get(base_map_idx, None): # 繝懊シ繝ウ莉ョ逋サ骭イ - is_add_random = False bone_name = self.get_bone_name(abb_name, v_yno, v_xno) if bone_name in model.bones or bone_name in tmp_all_bones: - # 莉ョ逋サ骭イ縺ョ譎らせ縺ァ荵ア謨ー縺ッ蠕後m縺ォ莉倥¢縺ヲ縺翫¥縺後√Γ繝繧サ繝シ繧ク縺ッ蠢隕√↑縺ョ縺縺大コ縺 - is_add_random = True bone_name += randomname(3) + logger.warning("蜷後§繝懊シ繝ウ蜷阪′譌「縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥懊シ繝ウ蜷: %s", bone_name) bone = Bone(bone_name, bone_name, vv.position().copy(), parent_bone.index, 0, 0x0000 | 0x0002) bone.local_z_vector = vv.normal().copy() @@ -4212,84 +5335,157 @@ def create_bone( bone.local_z_vector *= MVector3D(-1, 1, -1) if bone.local_z_vector == MVector3D(): bone.local_z_vector = MVector3D.crossProduct(bone.local_x_vector, MVector3D(1, 0, 0)) - bone.flag |= 0x0800 + # 繝ュ繝シ繧ォ繝ォ霆ク縺ゅj縺ァ蝗櫁サ「蜿ッ閭ス + bone.flag |= 0x0800 | 0x0002 if regist_bones[v_yidx, v_xidx]: - # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医ョ縺ソ繝懊シ繝ウ菫晄戟 + # 荳譌ヲ莉ョ逋サ骭イ vv.map_bones[base_map_idx] = bone - bone.index = len(tmp_all_bones) + len(model.bones) - if v_yidx == vertex_map.shape[0] - 1: - # 譛ォ遶ッ縺ッ髱櫁。ィ遉コ - regist_bones[v_yidx, v_xidx] = False - else: - # 縺昴l莉・螟悶ッ陦ィ遉コ縺ゅj縺ァ謫堺ス懷庄閭ス - bone.flag |= 0x0008 | 0x0010 + bone.index = len(model.bones) + len(tmp_all_bones) + tmp_all_bones[bone.name] = bone + tmp_all_bone_indexes[bone.index] = bone.name + tmp_all_bone_vvs[bone.name] = {"base_map_idx": base_map_idx, "vv": vv} + + # # 逋サ骭イ蟇セ雎。縺ョ蝣エ蜷医ョ縺ソ繝懊シ繝ウ菫晄戟 + # vv.map_bones[base_map_idx] = bone + # if is_regist: + # # 逋サ骭イ蟇セ雎。縺ァ縺ゅk蝣エ蜷医∽ク譌ヲ莉ョ逋サ骭イ + # bone.index = len(model.bones) + len(tmp_all_bones) + # tmp_all_bones[bone.name] = bone + # tmp_all_bone_indexes[bone.index] = bone.name + # elif substitute_bone: + # # 逋サ骭イ蟇セ雎。縺ァ縺ッ縺ェ縺蝣エ蜷医∝酔縺倅ス咲スョ縺ョ繝懊シ繝ウ繧貞盾辣ァ縺吶k + # # 莉ョ諠ウ鬆らせ縺ォ邏蝉サ倥¥繝懊シ繝ウ繧らオア荳縺吶k + # vv = virtual_vertices[bone.position.to_key(threshold)] + # for midx in vv.map_bones.keys(): + # vv.map_bones[midx] = substitute_bone + + logger.debug( + f"tmp_all_bones: {bone.name}, parent: {parent_bone.name}, pos: {bone.position.to_log()}" + ) - if is_add_random: - logger.warning("蜷後§繝懊シ繝ウ蜷阪′譌「縺ォ逋サ骭イ縺輔l縺ヲ縺繧九◆繧√∵忰蟆セ縺ォ荵ア謨ー繧定ソス蜉縺励∪縺吶 譌「蟄倥懊シ繝ウ蜷: %s", bone.name) + bone_cnt += 1 + if bone_cnt > 0 and bone_cnt // 1000 > prev_bone_cnt: + logger.info("-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ", base_map_idx + 1, bone_cnt) + prev_bone_cnt = bone_cnt // 1000 - # 逋サ骭イ蟇セ雎。縺ァ縺ゅk蝣エ蜷 - tmp_all_bones[bone.name] = bone + prev_xs.extend(list(range(vertex_map.shape[1]))) - logger.debug(f"tmp_all_bones: {bone.name}, pos: {bone.position.to_log()}") + logger.info("-- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ") - bone_cnt += 1 - if bone_cnt > 0 and bone_cnt // 1000 > prev_bone_cnt: - logger.info("-- --縲侵o.%s縲代懊シ繝ウ逕滓: %s蛟狗岼:邨ゆコ", base_map_idx + 1, bone_cnt) - prev_bone_cnt = bone_cnt // 1000 + tmp_all_bone_parents = {} + tmp_all_bone_targets = [] + for bi, bone_name in enumerate(tmp_all_bones.keys()): + bone = tmp_all_bones[bone_name] - prev_xs.extend(list(range(vertex_map.shape[1]))) + # 閾ェ霄ォ縺ィ蜷後§菴咲スョ縺ョ繝懊シ繝ウ繧定ヲェ縺ォ謖√▽蟄舌懊シ繝ウ + cbones = [ + cbone + for cbone in tmp_all_bones.values() + if cbone.index != root_bone.index + and ( + ( + cbone.parent_index in tmp_all_bone_indexes + and tmp_all_bone_indexes[cbone.parent_index] in tmp_all_bones + and tmp_all_bones[tmp_all_bone_indexes[cbone.parent_index]].position == bone.position + ) + or ( + cbone.parent_index in model.bone_indexes + and model.bone_indexes[cbone.parent_index] in model.bones + and model.bones[model.bone_indexes[cbone.parent_index]].position == bone.position + ) + ) + ] + + if not cbones: + # 蟄舌懊シ繝ウ縺後↑縺蝣エ蜷医√◎縺ョ縺セ縺セ逋サ骭イ + tmp_all_bone_parents[bone.name] = tmp_all_bone_indexes[bone.parent_index] + tmp_all_bone_targets.append(bone.name) + else: + cbone_poses = {} + for cbone in cbones: + pos = tuple(cbone.position.data().tolist()) + if pos not in cbone_poses: + cbone_poses[pos] = [] + cbone_poses[pos].append(cbone) + + for in_cbones in cbone_poses.values(): + tmp_all_bone_targets.append(in_cbones[0].name) + parent_bone_name = tmp_all_bone_indexes[in_cbones[0].parent_index] + tmp_all_bone_parents[in_cbones[0].name] = parent_bone_name + if len(in_cbones) > 1: + for cbone in in_cbones[1:]: + # 2縺、莉・荳翫≠繧句エ蜷医∝セ後ョ繝懊シ繝ウ縺ッ譛蛻昴ョ繝懊シ繝ウ縺ョ隕ェ繧剃サ」逕ィ縺吶k + tmp_all_bone_parents[cbone.name] = parent_bone_name + tmp_all_bone_targets.append(cbone.name) + + # 閾ェ蛻縺ョ隕ェ縺ッ逋サ骭イ蟇セ雎。螟悶→縺吶k + if cbone.parent_index in tmp_all_bone_indexes: + for n, pname in enumerate(tmp_all_bone_targets): + if pname == tmp_all_bone_indexes[cbone.parent_index]: + del tmp_all_bone_targets[n] + break + + if bi > 0 and bi % 100 == 0: + logger.info("-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ", bi) + + logger.info("-- -- 隕ェ繝懊シ繝ウ繝√ぉ繝繧ッ: %s蛟狗岼:邨ゆコ", bi) + + # 縺薙ョ繧ソ繧、繝溘Φ繧ー縺ァ荳ュ蠢繝懊シ繝ウ逋サ骭イ + model.bones[root_bone.name] = root_bone + model.bone_indexes[root_bone.index] = root_bone.name + model.display_slots[display_name].references.append((0, model.bones[root_bone.name].index)) + + logger.info("-- 繝懊シ繝ウ驟咲スョ") + + for bi, bone_name in enumerate(sorted(tmp_all_bones.keys())): + if bone_name not in tmp_all_bone_targets: + if bone_name in tmp_all_bone_vvs and tmp_all_bone_vvs[bone_name]["vv"].map_bones: + # 蜷後§邂謇縺ォ譌「縺ォ繝懊シ繝ウ螳夂セゥ縺後≠繧句エ蜷医√◎繧後r豬∫畑 + tmp_all_bone_vvs[bone_name]["vv"].map_bones[ + tmp_all_bone_vvs[bone_name]["base_map_idx"] + ] = tmp_all_bone_vvs[bone_name]["vv"].map_bones[ + list(tmp_all_bone_vvs[bone_name]["vv"].map_bones.keys())[0] + ] + if bi % 100 == 0: + logger.info("-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ", bi) + continue - # 縺セ縺壹ッ繧ス繝シ繝医@縺溘懊シ繝ウ蜷阪〒逋サ骭イ - registed_bone_names = {} - for bone_name in sorted(tmp_all_bones.keys()): bone = tmp_all_bones[bone_name] + bone.index = len(model.bones) + model.bones[bone.name] = bone + model.bone_indexes[bone.index] = bone_name - is_regist = True - for rbone_name in registed_bone_names.values(): - # 逋サ骭イ貂医∩縺ョ繝懊シ繝ウ繝ェ繧ケ繝医→豈碑シ - rbone = model.bones[rbone_name] - if ( - rbone.position == bone.position - and rbone.parent_index in model.bone_indexes - and bone.parent_index in model.bone_indexes - and model.bones[model.bone_indexes[rbone.parent_index]].position - == model.bones[model.bone_indexes[bone.parent_index]].position - ): - # 繝懊シ繝ウ讒区舌′縺セ縺」縺溘¥蜷後§蝣エ蜷医√%縺ョ繝懊シ繝ウ縺昴ョ繧ゅョ縺ッ逋サ骭イ蟇セ雎。螟 - is_regist = False - break + model.display_slots[display_name].references.append((0, bone.index)) + tmp_all_bone_vvs[bone.name]["vv"].map_bones[tmp_all_bone_vvs[bone.name]["base_map_idx"]] = bone - if is_regist: - registed_bone_names[bone.index] = bone_name - bone.index = len(model.bones) - model.bones[bone_name] = bone - model.bone_indexes[bone.index] = bone_name + if bone_name in tmp_all_bone_parents: + # 隕ェ繝懊シ繝ウ繧剃サ倥¢譖ソ縺医k蠢隕√′縺ゅk蝣エ蜷 + parent_bone_name = tmp_all_bone_parents[bone_name] + if parent_bone_name not in model.bones: + logger.warning( + "隕ェ繝懊シ繝ウ繧定ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∽クュ蠢繝懊シ繝ウ縺ォ邏蝉サ倥¢縺セ縺: 隕ェ縲%s縲大ュ舌%s縲", + parent_bone_name, + bone_name, + decoration=MLogger.DECORATION_BOX, + ) + parent_bone = root_bone + else: + parent_bone = model.bones[parent_bone_name] - model.display_slots[display_name].references.append((0, bone.index)) - else: - # 逋サ骭イ蟇セ雎。螟悶□縺」縺溷エ蜷医∝燕縺ォ逋サ骭イ縺輔l縺ヲ縺繧九懊シ繝ウ蜷阪r蜿らァ縺吶k - registed_bone_names[bone.index] = rbone_name - # 莉ョ諠ウ鬆らせ縺ォ邏蝉サ倥¥繝懊シ繝ウ繧らオア荳縺吶k - vv = virtual_vertices[bone.position.to_key(threshold)] - for midx in vv.map_bones.keys(): - vv.map_bones[midx] = rbone - - # 縺昴ョ蠕後〒隕ェ繝懊シ繝ウ繝サ陦ィ遉コ蜈医懊シ繝ウ縺ョINDEX繧貞繧頑崛縺医k - for bone_name in sorted(list(set(list(registed_bone_names.values())))): - bone = model.bones[bone_name] - parent_bone = root_bone - if bone.parent_index in registed_bone_names: - # 逋サ骭イ蜑阪ョINDEX縺九i蜷咲ァー繧貞シ輔▲蠑オ縺」縺ヲ縺阪※縲√◎繧後r譁ー縺励>INDEX縺ァ鄂ョ縺肴鋤縺医k - parent_bone = model.bones[registed_bone_names[bone.parent_index]] + # 逋サ骭イ蟇セ雎。縺ァ縺ゅk蝣エ蜷医√◎縺ョ縺セ縺セ逋サ骭イ bone.parent_index = parent_bone.index - # 隕ェ繝懊シ繝ウ縺ョ陦ィ遉コ蜈医b蜷梧凾險ュ螳 - if parent_bone != root_bone: - parent_bone.tail_index = bone.index - parent_bone.local_x_vector = (bone.position - parent_bone.position).normalized() - # 隕ェ繝懊シ繝ウ繧定。ィ遉コ蟇セ雎。縺ォ縺吶k - parent_bone.flag |= 0x0001 + if parent_bone != root_bone: + # 隕ェ繝懊シ繝ウ縺ョ陦ィ遉コ蜈亥崎ィュ螳 + parent_bone.tail_index = bone.index + # 隕ェ繝懊シ繝ウ縺ッ陦ィ遉コ縺ゅj縺ァ謫堺ス懷庄閭ス + parent_bone.flag |= 0x0008 | 0x0010 | 0x0001 + + if bi > 0 and bi % 100 == 0: + logger.info("-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ", bi) + + logger.info("-- -- 繝懊シ繝ウ驟咲スョ: %s蛟狗岼:邨ゆコ", bi) return ( root_bone, @@ -4552,7 +5748,7 @@ def create_bust_rigidbody( shape_size, shape_position, shape_rotation_radians, - param_rigidbody.param.mass if is_joint else 0.1, + param_rigidbody.param.mass / 2 if is_joint else param_rigidbody.param.mass, param_rigidbody.param.linear_damping, param_rigidbody.param.angular_damping, param_rigidbody.param.restitution, @@ -4564,7 +5760,13 @@ def create_bust_rigidbody( return rigidbody def create_bone_map( - self, model: PmxModel, param_option: dict, material_name: str, target_vertices: list, is_root_bone=True + self, + model: PmxModel, + param_option: dict, + material_name: str, + target_vertices: list, + base_vertical_axis: MVector3D, + is_root_bone=True, ): bone_grid = param_option["bone_grid"] bone_grid_cols = param_option["bone_grid_cols"] @@ -4622,7 +5824,7 @@ def create_bone_map( if weights[3] > 0: weighted_bone_indexes.append(v.deform.index3) - for bi0, bi1 in list(itertools.combinations(weighted_bone_indexes, 2)): + for bi0, bi1 in list(combinations(weighted_bone_indexes, 2)): # 繝懊シ繝ウ2縺、縺壹▽縺ョ繝壹い縺ァ繧ヲ繧ァ繧、繝育ケ九′繧雁キ蜷医r菫晄戟縺吶k key = (min(bi0, bi1), max(bi0, bi1)) if key not in weighted_bone_pairs: @@ -4677,6 +5879,7 @@ def create_bone_map( # 蟶縺ッ讓ェ縺ョ郢九′繧翫r繝√ぉ繝繧ッ縺吶k for v_yidx in range(vertex_map.shape[0]): + v_xidx = 0 for v_xidx in range(0, vertex_map.shape[1] - 1): if ( not np.isnan(vertex_map[v_yidx, v_xidx]).any() @@ -4693,7 +5896,8 @@ def create_bone_map( # 繧ヲ繧ァ繧、繝医r蜈ア譛峨☆繧九懊シ繝ウ縺ョ邨縺ソ蜷医o縺帙〒縺ゅ▲縺溷エ蜷医∵磁邯啜RUE bone_connected[v_yidx, v_xidx] = True - v_xidx += 1 + if v_xidx > 0: + v_xidx += 1 if not np.isnan(vertex_map[v_yidx, v_xidx]).any() and not np.isnan(vertex_map[v_yidx, 0]).any(): # 霈ェ繧呈緒縺縺溘ョ繧らケ九′縺」縺ヲ縺繧九°繝√ぉ繝繧ッ vv1 = virtual_vertices[tuple(vertex_map[v_yidx, v_xidx])] @@ -4754,21 +5958,49 @@ def create_bone_map( all_regist_bones[grid_col] = regist_bones vertex_maps[len(vertex_maps)] = vertex_map + vertex_positions = {} top_bone_positions = [] for vertex_map in vertex_maps.values(): - for vkey in vertex_map[0, :]: - if np.isnan(vkey).any() or tuple(vkey) not in virtual_vertices: - continue - top_bone_positions.append(virtual_vertices[tuple(vkey)].position().data()) + for v_yidx in range(vertex_map.shape[0]): + for vkey in vertex_map[v_yidx, :]: + if v_yidx == 0: + if np.isnan(vkey).any() or tuple(vkey) not in virtual_vertices: + continue + top_bone_positions.append(virtual_vertices[tuple(vkey)].position().data()) + vertex_positions[tuple(vkey)] = virtual_vertices[tuple(vkey)].position().data() # 荳ュ蠢繝懊シ繝ウ root_bone = None if is_root_bone: - _, root_bone = self.create_root_bone( - model, param_option, material_name, MVector3D(np.mean(top_bone_positions, axis=0)) + display_name, root_bone = self.create_root_bone( + model, param_option, material_name, MVector3D(np.mean(top_bone_positions, axis=0)), base_vertical_axis ) - return virtual_vertices, vertex_maps, all_regist_bones, all_bone_connected, root_bone + model.bones[root_bone.name] = root_bone + model.bone_indexes[root_bone.index] = root_bone.name + model.display_slots[display_name].references.append((0, model.bones[root_bone.name].index)) + else: + root_bone = model.bones[param_option["parent_bone_name"]] + + # 蜷鬆らせ縺ョ菴咲スョ縺ィ縺ョ蟾ョ蛻縺九i霍晞屬繧呈クャ繧 + v_distances = np.linalg.norm( + (np.array(list(vertex_positions.values())) - root_bone.position.data()), ord=2, axis=1 + ) + # 隕ェ繝懊シ繝ウ縺ォ譛繧りソ代>鬆らせ + nearest_vertex_idx = list(vertex_positions.keys())[np.argmin(v_distances)] + # 隕ェ繝懊シ繝ウ縺ォ譛繧る□縺鬆らせ + farest_vertex_idx = list(vertex_positions.keys())[np.argmax(v_distances)] + # 譚占ウェ蜈ィ菴薙ョ蛯セ縺 + material_direction = ( + MVector3D(vertex_positions[farest_vertex_idx] - vertex_positions[nearest_vertex_idx]) + .abs() + .normalized() + .data()[np.where(np.abs(base_vertical_axis.data()))] + )[0] + logger.info("%s: 譚占ウェ鬆らせ縺ョ蛯セ縺咲ョ怜コ: %s", material_name, round(material_direction, 5)) + is_material_horizonal = np.isclose(material_direction, 0.0) + + return virtual_vertices, vertex_maps, all_regist_bones, all_bone_connected, root_bone, is_material_horizonal def create_vertex_map( self, @@ -4816,7 +6048,7 @@ def create_vertex_map( if not vertex_positions: logger.warning("蟇セ雎。遽蝗イ縺ィ縺ェ繧矩らせ縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺", decoration=MLogger.DECORATION_BOX) - return None, None, None, None, None + return None, None, None, None, None, None, None material_mean_pos = MVector3D(np.mean(list(vertex_positions.values()), axis=0)) logger.info("%s: 譚占ウェ鬆らせ縺ョ荳ュ蠢轤ケ邂怜コ: %s", material_name, material_mean_pos.to_log()) @@ -4837,6 +6069,7 @@ def create_vertex_map( .data()[np.where(np.abs(base_vertical_axis.data()))] )[0] logger.info("%s: 譚占ウェ鬆らせ縺ョ蛯セ縺咲ョ怜コ: %s", material_name, round(material_direction, 5)) + is_material_horizonal = material_direction < 0.1 # 鬆らせ髢薙ョ霍晞屬 # https://blog.shikoan.com/distance-without-for-loop/ @@ -4845,7 +6078,7 @@ def create_vertex_map( ) all_vertex_distances = np.sqrt(np.sum(all_vertex_diffs**2, axis=-1)) # 鬆らせ蜷悟」ォ縺ョ霍晞屬縺九i髢セ蛟、逕滓 - threshold = np.min(all_vertex_distances[all_vertex_distances > 0]) * 0.8 + threshold = np.min(all_vertex_distances[all_vertex_distances > 0]) * 0.5 logger.info("%s: 譚占ウェ鬆らせ縺ョ髢セ蛟、邂怜コ: %s", material_name, round(threshold, 5)) @@ -4854,6 +6087,9 @@ def create_vertex_map( virtual_vertices = {} index_surface_normals = {} edge_pair_lkeys = {} + all_line_pairs = {} + all_indexes_vertices = [] + all_same_pair_edges = {} n = 0 for index_idx in model.material_indices[material_name]: # 鬆らせ縺ョ邨縺ソ蜷医o縺帙°繧蛾擇INDEX繧貞シ輔¥ @@ -4877,6 +6113,18 @@ def create_vertex_map( v1_key = v1.position.to_key(threshold) v2_key = v2.position.to_key(threshold) + for (l1, l2) in combinations([v0_key, v1_key, v2_key], 2): + if l1 not in all_line_pairs: + all_line_pairs[l1] = [] + if l2 not in all_line_pairs[l1]: + all_line_pairs[l1].append(l2) + + if l2 not in all_line_pairs: + all_line_pairs[l2] = [] + if l1 not in all_line_pairs[l2]: + all_line_pairs[l2].append(l1) + all_indexes_vertices.append(tuple(list(sorted([v0_key, v1_key, v2_key])))) + # 荳譌ヲ繝ォ繝シ繝医懊シ繝ウ縺ォ繧ヲ繧ァ繧、繝医r荳諡ャ鄂ョ謠 v0.deform = Bdef1(parent_bone.index) @@ -4908,7 +6156,7 @@ def create_vertex_map( v0_dot = MVector3D.dotProduct(material_normal, mean_line_segment) surface_dot = MVector3D.dotProduct(material_normal, surface_line_segment) - logger.debug( + logger.test( f"material_normal[{material_normal.to_log()}], mean_line_segment[{mean_line_segment.to_log()}], surface_line_segment[{surface_line_segment.to_log()}], v0_dot[{round(v0_dot, 3)}], surface_dot[{round(surface_dot, 3)}]" ) # (v1繝サn) * (v2繝サn) <= 0縺ェ繧峨ー邱壼縺ッ蟷ウ髱「縺ィ陦晉ェ√r襍キ縺薙@縺ヲ縺繧 @@ -4921,7 +6169,7 @@ def create_vertex_map( # parent_bone.position + -parent_direction * 1000, # parent_bone.position + parent_direction * 1000, # ) - # logger.debug( + # logger.test( # f"tt[{round(intersect_tt, 5)}], uu[{round(intersect_uu, 5)}], len[{round(intersect_len, 5)}], iv[{intersect_vec.to_log()}]" # ) # # 縺ゥ縺。繧峨°縺檎ッ蝗イ蜀縺ェ繧芽。ィ縲ゆク。譁ケ縺ィ繧らッ蝗イ螟悶↑繧芽」 @@ -4938,8 +6186,10 @@ def create_vertex_map( lkey = (min(vv0_key, vv1_key), max(vv0_key, vv1_key)) if lkey not in edge_pair_lkeys: edge_pair_lkeys[lkey] = [] + all_same_pair_edges[lkey] = [] if index_idx not in edge_pair_lkeys[lkey]: edge_pair_lkeys[lkey].append(index_idx) + all_same_pair_edges[lkey].append(vv2_key) if lkey not in index_surface_normals: index_surface_normals[lkey] = [] @@ -4954,7 +6204,7 @@ def create_vertex_map( if vv0_key not in remaining_vertices: remaining_vertices[vv0_key] = virtual_vertices[vv0_key] - logger.debug( + logger.test( f"笘陦ィ index[{index_idx}], v0[{v0.index}:{v0_key}], v1[{v1.index}:{v1_key}], v2[{v2.index}:{v2_key}], i[{round(intersect, 5)}], dot[{round(direction_dot, 4)}], mn[{mean_pos.to_log()}], sn[{surface_normal.to_log()}], pa[{parent_bone.position.to_log()}]" ) else: @@ -4962,88 +6212,520 @@ def create_vertex_map( back_vertices.append(v0_idx) back_vertices.append(v1_idx) back_vertices.append(v2_idx) - logger.debug( + logger.test( f"笘陬 index[{index_idx}], v0[{v0.index}:{v0_key}], v1[{v1.index}:{v1_key}], v2[{v2.index}:{v2_key}], i[{round(intersect, 5)}], dot[{round(direction_dot, 4)}], mn[{mean_pos.to_log()}], sn[{surface_normal.to_log()}], pa[{parent_bone.position.to_log()}]" ) n += 1 - if n > 0 and n % 500 == 0: + if n > 0 and n % 100 == 0: logger.info("-- 繝。繝繧キ繝・遒コ隱: %s蛟狗岼:邨ゆコ", n) if not virtual_vertices: logger.warning("蟇セ雎。遽蝗イ縺ィ縺ェ繧矩らせ縺悟叙蠕励〒縺阪↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺", decoration=MLogger.DECORATION_BOX) - return None, None, None, None, None + return None, None, None, None, None, None, None + + if not edge_pair_lkeys: + logger.warning("蟇セ雎。遽蝗イ縺ォ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\n髱「縺瑚。ィ陬丞渚霆「縺励※縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", decoration=MLogger.DECORATION_BOX) + return None, None, None, None, None, None, None + + logger.test("--------------------------") + + edge_line_pairs = {} + for n, ((min_vkey, max_vkey), line_iidxs) in enumerate(edge_pair_lkeys.items()): + surface_normals = index_surface_normals[(min_vkey, max_vkey)] + is_pair = False + if len(line_iidxs) <= 1: + is_pair = True + + logger.test( + f"笳 min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], only-one-index" + ) + else: + surface_dots = [MVector3D.dotProduct(surface_normals[0], sn) for sn in surface_normals] + surface_dot_diffs = np.abs(np.array(surface_dots) - surface_dots[0]) + if np.where(surface_dot_diffs < 0.2)[0].shape[0] == 1: + logger.test( + f"笆ウ min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], surface_dots[{[round(sd, 4) for sd in surface_dots]}], surface_diffs[{[round(sd, 4) for sd in surface_dot_diffs]}], surface-one-index" + ) + else: + logger.test( + f"テ min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], surface_dots[{[round(sd, 4) for sd in surface_dots]}], surface_diffs[{[round(sd, 4) for sd in surface_dot_diffs]}], multi-index" + ) + + if is_pair: + if min_vkey not in virtual_vertices or max_vkey not in virtual_vertices: + continue + + if min_vkey not in edge_line_pairs: + edge_line_pairs[min_vkey] = [] + if max_vkey not in edge_line_pairs: + edge_line_pairs[max_vkey] = [] + + edge_line_pairs[min_vkey].append(max_vkey) + edge_line_pairs[max_vkey].append(min_vkey) + + if n > 0 and n % 200 == 0: + logger.info("-- 霎コ遒コ隱: %s蛟狗岼:邨ゆコ", n) + + if logger.is_debug_level(): + logger.debug("--------------------------") + logger.debug("繧ィ繝繧ク繝壹い繝ェ繧ケ繝") + for v_key, pair_vkeys in edge_line_pairs.items(): + logger.debug( + f"key[{v_key}:{virtual_vertices[v_key].vidxs()}], pair[{pair_vkeys}:{[virtual_vertices[pair_vkey].vidxs() for pair_vkey in pair_vkeys]}]" + ) + + if param_option["special_shape"] == logger.transtext("髱「谺縺"): + logger.debug("莉ョ諠ウ髱「縺ョ遒コ隱") + + virtual_edges = [] + for n, (v0_key, pair_vertices) in enumerate(all_line_pairs.items()): + for (v1_key, v2_key) in combinations(pair_vertices, 2): + if not (v0_key in edge_line_pairs and v1_key in edge_line_pairs and v2_key in edge_line_pairs): + # 蜈ィ驛ィ繧ィ繝繧ク縺ォ縺ェ縺代l縺ー繧ケ繝ォ繝シ + continue + + ikey = tuple(list(sorted([v0_key, v1_key, v2_key]))) + if ikey in all_indexes_vertices: + # 譌「縺ォ髱「縺ョ繧ィ繝繧ク縺ョ邨縺ソ蜷医o縺帙〒縺ゅk蝣エ蜷医√せ繝ォ繝シ + continue + + edge_existed = {} + for (vv0_key, vv1_key) in combinations(set([v0_key, v1_key, v2_key]), 2): + lkey = (min(vv0_key, vv1_key), max(vv0_key, vv1_key)) + edge_existed[lkey] = lkey in all_same_pair_edges + + if 1 < Counter(edge_existed.values())[False]: + # 莉ョ諠ウ繧ィ繝繧ク縺1莉カ繧医j螟壹>蝣エ蜷医せ繝ォ繝シ + logger.debug( + "** テ嶺サョ諠ウ繧ィ繝繧ク繧ケ繝ォ繝シ: [%s:%s, %s:%s, %s:%s][%s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + edge_existed, + ) + continue + + logger.debug("----------------------") + logger.debug( + "** 笳倶サョ諠ウ繧ィ繝繧ク1莉カ: [%s:%s, %s:%s, %s:%s][%s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + edge_existed, + ) + + # 莉ョ諠ウ繧ィ繝繧ク + virtual_edge_keys = [e for e, v in edge_existed.items() if v == False] + if not virtual_edge_keys: + continue + virtual_edge_keys = virtual_edge_keys[0] + ve1_vec = virtual_vertices[virtual_edge_keys[0]].position() + ve2_vec = virtual_vertices[virtual_edge_keys[1]].position() + ve_line = MSegment(ve1_vec, ve2_vec) + + is_both_connected = False + for vkey in [v0_key, v1_key, v2_key]: + # if ( + # np.array( + # [ + # cv in virtual_vertices[vkey].connected_vvs + # for cv in virtual_vertices[virtual_edge_keys[0]].vidxs() + # ] + # ).any() + # and np.array( + # [ + # cv in virtual_vertices[vkey].connected_vvs + # for cv in virtual_vertices[virtual_edge_keys[1]].vidxs() + # ] + # ).any() + # ): + # 莉ョ諠ウ繧ィ繝繧ク縺ョ荳。譁ケ縺ォ郢九′縺」縺ヲ縺繧句エ蜷医∝遨阪′螟ァ縺阪¥驕輔≧莠具シ亥酔縺倩セコ縺ァ縺ェ縺縺薙→シ峨r繝√ぉ繝繧ッ + dot = MVector3D.dotProduct( + (virtual_vertices[vkey].position() - ve1_vec).normalized(), + (virtual_vertices[vkey].position() - ve2_vec).normalized(), + ) + if abs(dot) > 0.8: + is_both_connected = True + logger.debug( + "** テ怜酔荳霎コ驥崎、: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][p: [%s:%s]][%s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vkey, + virtual_vertices[vkey].vidxs(), + dot, + ) + break + else: + logger.debug( + "** 笳句酔荳霎コ驥崎、縺ェ縺: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][p: [%s:%s]][%s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vkey, + virtual_vertices[vkey].vidxs(), + dot, + ) + + if is_both_connected: + continue + + area_threshold = ( + np.mean( + [ + virtual_vertices[v0_key] + .position() + .distanceToPoint(virtual_vertices[v1_key].position()), + virtual_vertices[v0_key] + .position() + .distanceToPoint(virtual_vertices[v2_key].position()), + virtual_vertices[v1_key] + .position() + .distanceToPoint(virtual_vertices[v2_key].position()), + ] + ) + * 0.3 + ) + + # 鬆らせ縺ョ邨蜷医○縺ョ荳ュ縺ォ莉悶ョ鬆らせ縺悟性縺セ繧後※縺繧九° + is_inner_vkey = False + for vvkey in edge_line_pairs.keys(): + if not ( + vvkey in virtual_vertices[virtual_edge_keys[0]].connected_vvs + and vvkey in virtual_vertices[virtual_edge_keys[1]].connected_vvs + ): + # 繧ィ繝繧ク繧ュ繝シ縺梧磁邯壼医↓縺ェ縺蝣エ蜷医√せ繝ォ繝シ + continue + + # 繧ィ繝繧ク繧ュ繝シ縺御サョ諠ウ繧ィ繝繧ク縺ョ荳。譁ケ縺九i郢九′縺」縺ヲ縺繧句エ蜷医∬キ晞屬繝√ぉ繝繧ッ + min_length, h, t = calc_point_segment_dist(MPoint(virtual_vertices[vvkey].position()), ve_line) + if 0 < min_length < area_threshold: + is_inner_vkey = True + logger.debug( + "** テ鈴らせ蜀鬆らせ驥崎、: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][p: [%s:%s]][%s < %s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vvkey, + virtual_vertices[vvkey].vidxs(), + min_length, + area_threshold, + ) + break + else: + logger.debug( + "** 鬆らせ驥崎、縺ェ縺: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][p: [%s:%s]][%s < %s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vvkey, + virtual_vertices[vvkey].vidxs(), + min_length, + area_threshold, + ) + + if is_inner_vkey: + continue + + relation_vkeys = [v0_key, v1_key, v2_key] + for vk in [v0_key, v1_key, v2_key]: + relation_vkeys.extend(virtual_vertices[vk].connected_vvs) + relation_vkeys = set(relation_vkeys) + + is_intersect = False + for (vv0_key, vv1_key) in all_same_pair_edges.keys(): + if not (vv0_key in relation_vkeys and vv1_key in relation_vkeys): + # 髢「菫ゅ☆繧矩らせ縺ァ縺ェ縺蝣エ蜷医せ繝ォ繝シ + logger.test( + "** テ嶺コ、蟾ョ辟。髢「菫ゅせ繝ォ繝シ: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][vv: [%s:%s, %s:%s]]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + ) + continue + + if len({vv0_key, vv1_key} - {v0_key, v1_key, v2_key}) == 0: + # 蜈ィ驛ィ莉ョ諠ウ髱「縺ョ鬆らせ縺ョ蝣エ蜷医∬ヲ九↑縺上※縺縺縺ョ縺ァ繧ケ繝ォ繝シ + logger.debug( + "** テ嶺サョ諠ウ髱「繧ケ繝ォ繝シ: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][vv: [%s:%s, %s:%s]]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + ) + continue + + if len({vv0_key, vv1_key} - {virtual_edge_keys[0], virtual_edge_keys[1]}) == 1: + # 蜷後§鬆らせ縺梧ョ九▲縺ヲ縺繧句エ蜷医∽コ、蟾ョ縺ッ隕九↑縺上※縺縺縺ョ縺ァ繧ケ繝ォ繝シ + logger.debug( + "** テ嶺コ、蟾ョ莠、轤ケ繧ケ繝ォ繝シ: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][vv: [%s:%s, %s:%s]]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + ) + continue + + vv1_vec = virtual_vertices[vv0_key].position() + vv2_vec = virtual_vertices[vv1_key].position() + vv_line = MSegment(vv1_vec, vv2_vec) + min_length, p1, p2, t1, t2 = calc_segment_segment_dist(vv_line, ve_line) + if 0 < min_length < area_threshold * 1.5 and t1 and t2: + # 邱壼縺後≠縺」縺ヲ縲髢セ蛟、繧医j蟆上&縺蝣エ蜷医∽コ、蟾ョ縺励※縺繧九→隕九↑縺 + is_intersect = True + logger.debug( + "** テ嶺コ、蟾ョ縺ゅj: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][vv: [%s:%s, %s:%s]][%s < %s, %s, %s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + min_length, + area_threshold, + round(t1, 5), + round(t2, 5), + ) + break + else: + logger.debug( + "** 笳倶コ、蟾ョ縺ェ縺: [%s:%s, %s:%s, %s:%s][ve: [%s:%s, %s:%s]][vv: [%s:%s, %s:%s]][%s < %s, %s, %s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), + virtual_edge_keys[0], + virtual_vertices[virtual_edge_keys[0]].vidxs(), + virtual_edge_keys[1], + virtual_vertices[virtual_edge_keys[1]].vidxs(), + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + min_length, + area_threshold, + round(t1, 5), + round(t2, 5), + ) - if not edge_pair_lkeys: - logger.warning("蟇セ雎。遽蝗イ縺ォ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\n髱「縺瑚。ィ陬丞渚霆「縺励※縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", decoration=MLogger.DECORATION_BOX) - return None, None, None, None, None + if is_intersect: + # 譌「蟄倥ョ繧ィ繝繧ク縺ィ莠、蟾ョ縺励※縺縺溘i繧ケ繝ォ繝シ + continue - logger.debug("--------------------------") - edge_line_pairs = {} - for n, ((min_vkey, max_vkey), line_iidxs) in enumerate(edge_pair_lkeys.items()): - surface_normals = index_surface_normals[(min_vkey, max_vkey)] - is_pair = False - if len(line_iidxs) <= 1: - is_pair = True + # area = poly_area( + # np.array( + # [ + # virtual_vertices[v0_key].position().data(), + # virtual_vertices[v1_key].position().data(), + # virtual_vertices[v2_key].position().data(), + # ] + # ) + # ) + # if area < area_threshold: + # # 髢セ蛟、縺ョ荳螳夐上r雜縺医↑縺縺ョ縺ッ繧ケ繝ォ繝シシ亥、壼逶エ邱壻ク奇シ + # logger.debug( + # "** テ鈴擇遨阪せ繝ォ繝シ: [%s:%s, %s:%s, %s:%s][%s < %s]", + # v0_key, + # virtual_vertices[v0_key].vidxs(), + # v1_key, + # virtual_vertices[v1_key].vidxs(), + # v2_key, + # virtual_vertices[v2_key].vidxs(), + # area, + # area_threshold, + # ) + # continue + # logger.debug( + # "** 笳矩擇遨: [%s:%s, %s:%s, %s:%s][%s < %s]", + # v0_key, + # virtual_vertices[v0_key].vidxs(), + # v1_key, + # virtual_vertices[v1_key].vidxs(), + # v2_key, + # virtual_vertices[v2_key].vidxs(), + # area, + # threshold, + # ) - logger.debug( - f"笳 min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], only-one-index" - ) - else: - surface_dots = [MVector3D.dotProduct(surface_normals[0], sn) for sn in surface_normals] - surface_dot_diffs = np.abs(np.array(surface_dots) - surface_dots[0]) - if np.where(surface_dot_diffs < 0.2)[0].shape[0] == 1: logger.debug( - f"笆ウ min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], surface_dots[{[round(sd, 4) for sd in surface_dots]}], surface_diffs[{[round(sd, 4) for sd in surface_dot_diffs]}], surface-one-index" + "* 莉ョ諠ウ髱「: [%s:%s, %s:%s, %s:%s]", + v0_key, + virtual_vertices[v0_key].vidxs(), + v1_key, + virtual_vertices[v1_key].vidxs(), + v2_key, + virtual_vertices[v2_key].vidxs(), ) - else: - logger.debug( - f"テ min_vkey: [{min_vkey}({virtual_vertices[min_vkey].vidxs()})], max_vkey: [{max_vkey}({virtual_vertices[max_vkey].vidxs()})], line_iidxs: [{line_iidxs}], surface_dots[{[round(sd, 4) for sd in surface_dots]}], surface_diffs[{[round(sd, 4) for sd in surface_dot_diffs]}], multi-index" + logger.info( + "-- %s: 莉ョ諠ウ髱「霑ス蜉: [%s, %s, %s]", + material_name, + virtual_vertices[v0_key].vidxs(), + virtual_vertices[v1_key].vidxs(), + virtual_vertices[v2_key].vidxs(), ) - if is_pair: - if min_vkey not in virtual_vertices or max_vkey not in virtual_vertices: - continue + # 鬆らせ繧堤ケ九£縺溯セコ縺後お繝繧ク繝壹い縺ォ蜷ォ縺セ繧後※縺ェ縺蝣エ蜷医∽サョ諠ウ髱「繧定ソス蜉縺吶k + for (vv0_key, vv1_key) in combinations(set([v0_key, v1_key, v2_key]), 2): + lkey = (min(vv0_key, vv1_key), max(vv0_key, vv1_key)) - if min_vkey not in edge_line_pairs: - edge_line_pairs[min_vkey] = [] - if max_vkey not in edge_line_pairs: - edge_line_pairs[max_vkey] = [] + if vv0_key in virtual_edge_keys and vv1_key in virtual_edge_keys and lkey not in virtual_edges: + # 莉ョ諠ウ繧ィ繝繧ク縺ョ蝣エ蜷医∬ソス蜉 + if vv0_key not in edge_line_pairs: + edge_line_pairs[vv0_key] = [] + if vv1_key not in edge_line_pairs: + edge_line_pairs[vv1_key] = [] - edge_line_pairs[min_vkey].append(max_vkey) - edge_line_pairs[max_vkey].append(min_vkey) + edge_line_pairs[vv0_key].append(vv1_key) + edge_line_pairs[vv1_key].append(vv0_key) - if n > 0 and n % 200 == 0: - logger.info("-- 霎コ遒コ隱: %s蛟狗岼:邨ゆコ", n) + virtual_edges.append(lkey) + else: + # 莉ョ諠ウ繧ィ繝繧ク縺ァ縺ッ縺ェ縺蝣エ蜷医√お繝繧ク縺九i髯、螟 + for vvv0_key, vvv1_key in [(vv0_key, vv1_key), (vv1_key, vv0_key)]: + if vvv0_key in edge_line_pairs: + for n, vk in enumerate(edge_line_pairs[vvv0_key]): + if vk == vvv1_key: + del edge_line_pairs[vvv0_key][n] + break + if not edge_line_pairs[vvv0_key]: + del edge_line_pairs[vvv0_key] + + # 謗・邯壼医b霑ス蜉 + for vvkey in [v0_key, v1_key, v2_key]: + for rvvkey in set([v0_key, v1_key, v2_key]) - {vvkey}: + if rvvkey not in virtual_vertices[vvkey].connected_vvs: + virtual_vertices[vvkey].connected_vvs.append(rvvkey) - if logger.is_debug_level(): - logger.debug("--------------------------") - logger.debug("繧ィ繝繧ク繝壹い繝ェ繧ケ繝") - for v_key, pair_vkeys in edge_line_pairs.items(): - logger.debug( - f"key[{v_key}:{virtual_vertices[v_key].vidxs()}], pair[{pair_vkeys}:{[virtual_vertices[pair_vkey].vidxs() for pair_vkey in pair_vkeys]}]" - ) + if n > 0 and n % 20 == 0: + logger.info("-- 莉ョ諠ウ髱「遒コ隱: %s蛟狗岼:邨ゆコ", n) + + logger.debug( + "莉ョ諠ウ繧ィ繝繧ク: %s", + ", ".join( + [ + "[{0}:{1}, {2}:{3}]".format( + vv0_key, + virtual_vertices[vv0_key].vidxs(), + vv1_key, + virtual_vertices[vv1_key].vidxs(), + ) + for vv0_key, vv1_key in virtual_edges + ] + ), + ) logger.info("%s: 繧ィ繝繧ク縺ョ謚ス蜃コ貅門y", material_name) # 繧ィ繝繧ク繧堤ケ九>縺ァ縺縺 tmp_edge_lines = [] edge_vkeys = [] - while len(edge_vkeys) < len(edge_line_pairs.keys()): - _, tmp_edge_lines, edge_vkeys = self.get_edge_lines( - edge_line_pairs, None, tmp_edge_lines, edge_vkeys, param_option + n = 0 + remain_start_vkeys = list(edge_line_pairs.keys()) + remain_existed_edges = list(edge_line_pairs.keys()) + while remain_existed_edges: + registered_edge_line_pairs = {} + _, tmp_edge_lines, edge_vkeys, registered_edge_line_pairs = self.get_edge_lines( + edge_line_pairs, + registered_edge_line_pairs, + None, + tmp_edge_lines, + edge_vkeys, + virtual_vertices, + param_option, + 0, + n, ) + remain_start_vkeys = [elp for elp in edge_line_pairs.keys() if edge_line_pairs[elp]] + remain_existed_edges = set([vk for vk in remain_start_vkeys if vk in edge_line_pairs]) + n += 1 + logger.info("-- 繧ィ繝繧ク讀懷コ: %s蛟狗岼:邨ゆコ", n) all_edge_lines = [] for n, edge_lines in enumerate(tmp_edge_lines): - if len(edge_lines) < 3: + if 0 < len(edge_lines) < 3: logger.info( "-- %s: 讀懷コ繧ィ繝繧クシ井サカ謨ー縺悟ー代↑縺縺溘a蟇セ雎。螟厄シ: %s", material_name, [f"{ekey}:{virtual_vertices[ekey].vidxs()}" for ekey in edge_lines], ) - else: + elif edge_lines: logger.info( "-- %s: 讀懷コ繧ィ繝繧ク: %s", material_name, @@ -5055,7 +6737,7 @@ def create_vertex_map( logger.warning( "繧ィ繝繧ク縺梧、懷コ縺ァ縺阪↑縺九▲縺溘◆繧√∝ヲ逅繧剃クュ譁ュ縺励∪縺吶\n陬城擇縺ョ縺ゅk譚占ウェ縺ァ縲後☆縺ケ縺ヲ陦ィ髱「縲阪r驕ク謚槭@縺ヲ縺ェ縺縺九∫「コ隱阪@縺ヲ縺上□縺輔>縲", decoration=MLogger.DECORATION_BOX ) - return None, None, None, None, None + return None, None, None, None, None, None, None # if len(all_edge_lines) == 1 and not param_option["top_vertices_csv"]: # logger.warning( @@ -5065,55 +6747,82 @@ def create_vertex_map( logger.info("%s: 繧ィ繝繧ク縺ョ謚ス蜃コ", material_name) - all_mean_poses = [] - all_edge_poses = [] - target_diff_dots = [] - for n, edge_lines in enumerate(all_edge_lines): - all_edge_poses.append([]) - target_diff_dots.append([]) - - for prev_edge_key, now_edge_key, next_edge_key in zip( - edge_lines, edge_lines[1:] + edge_lines[:1], edge_lines[2:] + edge_lines[:2] - ): - prev_edge_pos = virtual_vertices[prev_edge_key].position() - now_edge_pos = virtual_vertices[now_edge_key].position() - next_edge_pos = virtual_vertices[next_edge_key].position() - - target_diff_dots[-1].append( - MVector3D.dotProduct( - (next_edge_pos - now_edge_pos).normalized(), (now_edge_pos - prev_edge_pos).normalized() - ) - ) - - all_edge_poses[-1].append(now_edge_pos.data()) - all_mean_poses.append(now_edge_pos.data()) + # all_edge_keys = [] + # all_mean_poses = [] + # all_edge_poses = [] + # target_diff_dots = [] + # for n, edge_lines in enumerate(all_edge_lines): + # all_edge_poses.append([]) + # target_diff_dots.append([]) + + # for n, (prev_edge_key, now_edge_key, next_edge_key) in enumerate( + # zip(edge_lines, edge_lines[1:] + edge_lines[:1], edge_lines[2:] + edge_lines[:2]) + # ): + # prev_edge_pos = virtual_vertices[prev_edge_key].position() + # now_edge_pos = virtual_vertices[now_edge_key].position() + # next_edge_pos = virtual_vertices[next_edge_key].position() + + # if n == 0: + # target_diff_dots[-1].append(1) + # else: + # target_diff_dots[-1].append( + # MVector3D.dotProduct( + # (next_edge_pos - now_edge_pos).normalized(), (now_edge_pos - prev_edge_pos).normalized() + # ) + # ) + + # all_edge_poses[-1].append(now_edge_pos.data()) + # all_mean_poses.append(now_edge_pos.data()) + # all_edge_keys.append(now_edge_key) # top縺ッ蜈ィ驛ィ荳ヲ蛻 - all_top_edge_distances = [] - all_top_edge_keys = [] - all_top_edge_poses = [] - all_top_edge_dots = [] - horizonal_top_edge_keys = [] - - # 蜃ヲ逅蟇セ雎。鬆らせ縺ョ霍晞屬縺ョ荳ュ螟ョ蛟、 - # if param_option["direction"] in [logger.transtext("荳"), logger.transtext("荳")]: - # mean_distances = np.linalg.norm((np.array(all_mean_poses) - parent_bone.position.data()), ord=2, axis=1) + if is_material_horizonal: + # 荳ヲ蛻励ョ蝣エ蜷医∬ソ代>譁ケ繧偵Ν繝シ繝医→縺吶k + all_root_key_poses = np.array([virtual_vertices[el[0]].position().data() for el in all_edge_lines]) + all_root_key_idx = np.argmin(np.linalg.norm(all_root_key_poses - material_mean_pos.data(), ord=2, axis=1)) + all_root_key = all_edge_lines[all_root_key_idx][0] + else: + # 蟋狗せ繧偵Ν繝シ繝医→縺吶kシ井ク区婿蜷代ョ蝣エ蜷医√そ繝ウ繧ソ繝シ縺ョ逵溷セ後m蛛エシ + all_root_key = all_edge_lines[0][0] + + # # 蜃ヲ逅蟇セ雎。鬆らせ縺ョ霍晞屬縺ョ蝓コ貅門、(縺ァ縺阪k縺縺第ケ蜈縺ョ蛟、) + # if is_material_horizonal: + # # 豌エ蟷ウ縺ョ蝣エ蜷医∝ィ菴薙ョ霍晞屬縺九i蟆上&縺縺ョ繧帝∈縺カ + # all_root_key_idx = np.argmin( + # np.linalg.norm((np.array(all_mean_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1) + # ) + # all_root_val = np.min( + # np.linalg.norm((np.array(all_mean_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1) + # ) + # all_mean_distance = np.mean( + # np.linalg.norm((np.array(all_mean_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1) + # ) # else: - mean_distances = np.linalg.norm((np.array(all_mean_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1) - mean_distance = np.mean(mean_distances) + # # 隗貞コヲ縺後≠繧句エ蜷医√ヮ繧、繧コ縺悟・繧峨↑縺繧医≧荳霆ク縺ァ縺ョ縺ソ蛻、螳壹☆繧 + # if param_option["direction"] in [logger.transtext("荳"), logger.transtext("蟾ヲ")]: + # all_root_val = np.min(all_mean_poses, axis=0)[target_idx] + # all_root_key_idx = np.argmin(all_mean_poses, axis=0)[target_idx] + # else: + # all_root_val = np.max(all_mean_poses, axis=0)[target_idx] + # all_root_key_idx = np.argmax(all_mean_poses, axis=0)[target_idx] + # all_mean_distance = np.abs(np.mean(np.array(all_mean_poses)[:, target_idx] - all_root_val)) + # all_root_key = all_edge_keys[all_root_key_idx] # 譬ケ蜈鬆らせCSV縺梧欠螳壹&繧後※縺繧句エ蜷医∝ッセ雎。鬆らせ繝ェ繧ケ繝育函謌 if param_option["top_vertices_csv"]: top_target_vertices = read_vertices_from_file(param_option["top_vertices_csv"], model, material_name) if not top_target_vertices: logger.warning("譬ケ蜈鬆らせCSV縺梧ュ」蟶ク縺ォ隱ュ縺ソ霎シ繧√↑縺九▲縺溘◆繧√∝ヲ逅繧堤オゆコ縺励∪縺", decoration=MLogger.DECORATION_BOX) - return None, None, None, None, None + return None, None, None, None, None, None, None # 譬ケ蜈鬆らせ繧ュ繝シ繝ェ繧ケ繝育函謌 for vidx in top_target_vertices: v = model.vertex_dict[vidx] + if v.index not in target_vertices: + continue + # 莉ョ諠ウ鬆らせ逋サ骭イシ郁ゥイ蠖馴らせ蟇セ雎。シ vkey = v.position.to_key(threshold) if vkey not in virtual_vertices: @@ -5122,115 +6831,177 @@ def create_vertex_map( horizonal_top_edge_keys.append(vkey) else: - for n, (edge_lines, edge_poses, target_dots) in enumerate( - zip(all_edge_lines, all_edge_poses, target_diff_dots) - ): - if param_option["direction"] in [logger.transtext("荳"), logger.transtext("荳")]: - edge_distances = np.linalg.norm( - (np.array(edge_poses) - parent_bone.position.data()), ord=2, axis=1 - ) - else: - edge_distances = np.linalg.norm( - (np.array(edge_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1 - ) - edge_mean_distance = np.mean(edge_distances) - if len(all_edge_lines) == 2 and edge_mean_distance < mean_distance: - # 繧ィ繝繧ク縺2縺、縺ョ蝣エ蜷医∝濠蛻縺ァ蛻縺代k(荳句承縺ッ螟ァ縺阪>譁ケ縲∽ク雁キヲ縺ッ蟆上&縺譁ケ) - all_top_edge_keys = edge_lines - all_top_edge_poses = edge_poses - all_top_edge_dots = target_dots - all_top_edge_distances = edge_distances - - if len(all_edge_lines) != 2 and np.array(edge_lines)[edge_distances < mean_distance].shape[0] > 0: - # 霍晞屬縺悟ィ菴薙ョ霍晞屬繧医j霑代>蝣エ蜷医∽ク企Κ縺ィ縺ソ縺ェ縺 - for idx in np.where(edge_distances < mean_distance)[0]: - all_top_edge_keys.append(edge_lines[idx]) - all_top_edge_poses.append(edge_poses[idx]) - all_top_edge_dots.append(target_dots[idx]) - all_top_edge_distances.append(edge_distances[idx]) - - if not all_top_edge_keys: - logger.warning( - "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳企Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", - decoration=MLogger.DECORATION_BOX, - ) - return None, None, None, None, None + # 譬ケ蜈鬆らせCSV縺梧欠螳壹&繧後※縺縺ェ縺蝣エ蜷 + # 譛繧ゅく繝シ縺御ク翫ョ荳轤ケ縺九i螟ァ菴捺ーエ蟷ウ縺ォ郢九′縺」縺ヲ縺繧玖セコ繧剃ク企Κ繧ィ繝繧ク縺ィ縺吶k + # 譌「蟄倥ョ繝ゥ繧、繝ウ縺ィ騾譁ケ蜷代ョ繝ゥ繧、繝ウ繧定ゥヲ縺 + for target_edge_lines, is_reverse in [ + (all_edge_lines, False), + ([list(reversed(ael)) for ael in all_edge_lines], True), + ]: + for n, edge_lines in enumerate(target_edge_lines): + if all_root_key not in edge_lines: + # 縺昴b縺昴b繝ォ繝シ繝医く繝シ縺悟性縺セ繧後※縺ェ縺代l縺ー繧ケ繝ォ繝シ + continue - vertical_top_edge_keys = [] + root_key_idx = [n for n, el in enumerate(edge_lines) if el == all_root_key][0] - # 荳サ縺ォ遘サ蜍輔☆繧玖サクシ域ーエ蟷ウシ啝縲∽ク贋ク具シ唳縲∝キヲ蜿ウシ唸シ - move_idx = ( - 2 - if material_direction == 0 - else 1 - if param_option["direction"] in [logger.transtext("荳"), logger.transtext("荳")] - else 0 - ) - top_move_values = np.array(all_top_edge_poses)[:, move_idx] + if edge_lines[0] == edge_lines[-1]: + del edge_lines[-1] - # 縺ョ譛螟ァ縺ョ1/2繧帝明蛟、縺ィ縺吶k - horizonal_threshold = np.max(np.abs(np.diff(top_move_values))) / 2 + for m, (prev_edge_key, now_edge_key, next_edge_key) in enumerate( + zip( + edge_lines[(root_key_idx - 1) :] + edge_lines[: (root_key_idx - 1)], + edge_lines[(root_key_idx):] + edge_lines[:(root_key_idx)], + edge_lines[(root_key_idx + 1) :] + edge_lines[: (root_key_idx + 1)], + ) + ): + if m == 0: + if is_reverse: + # 蜿崎サ「縺ッ0逡ェ逶ョ縺ッ譌「縺ォ蜈・縺」縺ヲ繧九ョ縺ァ now 縺ョ縺ソ + horizonal_top_edge_keys.insert(0, now_edge_key) + else: + horizonal_top_edge_keys.append(prev_edge_key) + horizonal_top_edge_keys.append(now_edge_key) + elif m > 0: + if is_reverse: + horizonal_top_edge_keys.insert(0, now_edge_key) + else: + horizonal_top_edge_keys.append(now_edge_key) - # 蜀遨榊キョ縺ョ譛螟ァ縺ョ1/2繧帝明蛟、縺ィ縺吶k(縺溘□縺励∵怙荳矩剞繧定ィュ縺代k) - dot_threshold = max(0.2, np.max(np.abs(np.diff(all_top_edge_dots))) / 2) + prev_edge_pos = virtual_vertices[prev_edge_key].position() + now_edge_pos = virtual_vertices[now_edge_key].position() + next_edge_pos = virtual_vertices[next_edge_key].position() - logger.debug( - f"horizonal_threshold: [{round(horizonal_threshold, 5)}], dot_threshold: [{round(dot_threshold, 5)}]" - ) + # 繧ィ繝繧ク縺ョ蜀遨 + dot = MVector3D.dotProduct( + (next_edge_pos - now_edge_pos).normalized(), + (now_edge_pos - prev_edge_pos).normalized(), + ) - # 螟画峇轤ケ繧呈アゅa繧 - target_idx_pose_f_prime_diff = np.where(np.abs(np.diff(all_top_edge_dots)) >= dot_threshold)[0] + # 繧ィ繝繧ク縺ョ隧穂セ。霆ク縺ョ螟牙虚 + distance = abs( + abs(next_edge_pos.data()[target_idx] - now_edge_pos.data()[target_idx]) + - abs(now_edge_pos.data()[target_idx] - prev_edge_pos.data()[target_idx]) + ) - logger.debug(f"target_idx_pose_f_prime_diff: [{np.round(target_idx_pose_f_prime_diff, decimals=3)}]") + logger.debug( + "now: %s, dot: %s, distance: %s, threshold: %s", + virtual_vertices[now_edge_key].vidxs(), + round(dot, 3), + round(distance, 3), + round(threshold, 3), + ) - if len(target_idx_pose_f_prime_diff) < 3 or np.isclose(horizonal_threshold, 0, rtol=1e-02, atol=1e-04): - # 螟画峇轤ケ縺御ク譫夂黄シ亥屁隗偵〒縺ェ縺シ牙エ蜷医√⊇縺シ蝮荳縺ァ縺ゅk蝣エ蜷医√お繝繧ク縺悟插荳縺ォ豌エ蟷ウ縺ォ郢九′縺」縺ヲ繧九→縺ソ縺ェ縺 - horizonal_top_edge_keys = all_top_edge_keys - else: - target_idx_pose_indices = ( - [0] + (target_idx_pose_f_prime_diff[::2] + 1).tolist() + [len(top_move_values)] - ) + if dot < 0.5 and (is_material_horizonal or distance > threshold): + break - # 隗貞コヲ縺ョ螟画峇轤ケ縺3縺、莉・荳翫≠繧句エ蜷医√お繝繧ク縺悟譁ュ縺輔l縺ヲ繧九→縺ソ縺ェ縺 - for ssi, esi in zip(target_idx_pose_indices, target_idx_pose_indices[1:]): - target_all_top_edge_keys = ( - all_top_edge_keys[ssi : (esi + 2)] if 0 == ssi else all_top_edge_keys[(ssi + 1) : (esi + 1)] - ) - slice_top_move_values = top_move_values[ssi : (esi + 1)] + # if is_material_horizonal: + # edge_distances = np.linalg.norm( + # (np.array(edge_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1 + # ) + # else: + # edge_distances = np.abs(np.array(edge_poses)[:, target_idx] - all_root_val) + # edge_mean_distance = np.mean(edge_distances) + # if len(all_edge_lines) == 2 and edge_mean_distance < all_mean_distance: + # # 繧ィ繝繧ク縺2縺、縺ョ蝣エ蜷医∝濠蛻縺ァ蛻縺代k(荳句承縺ッ螟ァ縺阪>譁ケ縲∽ク雁キヲ縺ッ蟆上&縺譁ケ) + # all_top_edge_keys = edge_lines + # all_top_edge_poses = edge_poses + # all_top_edge_dots = target_dots + # all_top_edge_distances = edge_distances + + # if len(all_edge_lines) != 2 and np.array(edge_lines)[edge_distances < edge_mean_distance].shape[0] > 0: + # # 霍晞屬縺悟ィ菴薙ョ霍晞屬繧医j霑代>蝣エ蜷医∽ク企Κ縺ィ縺ソ縺ェ縺 + # for idx in np.where(edge_distances < edge_mean_distance)[0]: + # all_top_edge_keys.append(edge_lines[idx]) + # all_top_edge_poses.append(edge_poses[idx]) + # all_top_edge_dots.append(target_dots[idx]) + # all_top_edge_distances.append(edge_distances[idx]) + + # if not all_top_edge_keys: + # logger.warning( + # "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳企Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", + # decoration=MLogger.DECORATION_BOX, + # ) + # return None, None, None, None, None - if len(slice_top_move_values) < 2: - # diff縺悟叙繧後↑縺縺上i縺蟆上&縺縺ョ縺ッ辟。隕 - logger.debug( - f"SKIP ssi[{ssi}], esi[{esi}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" - ) - continue + # vertical_top_edge_keys = [] - sliced_diff = np.mean(np.abs(np.diff(slice_top_move_values))) + # # 荳サ縺ォ遘サ蜍輔☆繧玖サクシ域ーエ蟷ウシ啝縲∽ク贋ク具シ唳縲∝キヲ蜿ウシ唸シ + # move_idx = ( + # 2 + # if material_direction == 0 + # else 1 + # if param_option["direction"] in [logger.transtext("荳"), logger.transtext("荳")] + # else 0 + # ) + # top_move_values = np.array(all_top_edge_poses)[:, move_idx] - if sliced_diff <= horizonal_threshold: - # 蜷御ク譁ケ蜷代ョ蛯セ縺阪↓螟牙喧縺悟ー上&縺代l縺ー縲∵ーエ蟷ウ譁ケ蜷 - horizonal_top_edge_keys.extend(target_all_top_edge_keys) + # # 遘サ蜍暮上ョ荳ュ螟ョ縺ョ1/2繧帝明蛟、縺ィ縺吶k + # horizonal_threshold = np.median(np.abs(np.diff(top_move_values))) * 1.5 - logger.debug( - f"HOR ssi[{ssi}], esi[{esi}], th[{horizonal_threshold}], sd[{sliced_diff}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" - ) - else: - # 蜷御ク譁ケ蜷代ョ蛯セ縺阪↓螟牙喧縺後≠繧後ー縲∝桙逶エ譁ケ蜷 - vertical_top_edge_keys.extend(target_all_top_edge_keys) + # # 蜀遨榊キョ縺ョ譛螟ァ縺ョ1/2繧帝明蛟、縺ィ縺吶k(縺溘□縺励∵怙荳矩剞繧定ィュ縺代k) + # dot_threshold = max(0.2, np.max(np.abs(np.diff(np.abs(all_top_edge_dots)))) * 0.5) - logger.debug( - f"VER ssi[{ssi}], esi[{esi}], th[{horizonal_threshold}], sd[{sliced_diff}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" - ) + # logger.debug( + # f"horizonal_threshold: [{round(horizonal_threshold, 5)}], dot_threshold: [{round(dot_threshold, 5)}]" + # ) + + # # 螟画峇轤ケ繧呈アゅa繧 + # target_idx_pose_f_prime_diff = np.where(np.abs(np.diff(all_top_edge_dots)) >= dot_threshold)[0] + + # logger.debug(f"target_idx_pose_f_prime_diff: [{np.round(target_idx_pose_f_prime_diff, decimals=3)}]") + + # if len(target_idx_pose_f_prime_diff) < 3: + # # 螟画峇轤ケ縺御ク譫夂黄シ亥屁隗偵〒縺ェ縺シ牙エ蜷医√⊇縺シ蝮荳縺ァ縺ゅk蝣エ蜷医√お繝繧ク縺悟插荳縺ォ豌エ蟷ウ縺ォ郢九′縺」縺ヲ繧九→縺ソ縺ェ縺 + # horizonal_top_edge_keys = all_top_edge_keys + # else: + # target_idx_pose_indices = ( + # [0] + (target_idx_pose_f_prime_diff[::2] + 1).tolist() + [len(top_move_values)] + # ) + + # # 隗貞コヲ縺ョ螟画峇轤ケ縺3縺、莉・荳翫≠繧句エ蜷医√お繝繧ク縺悟譁ュ縺輔l縺ヲ繧九→縺ソ縺ェ縺 + # for ssi, esi in zip(target_idx_pose_indices, target_idx_pose_indices[1:]): + # target_all_top_edge_keys = ( + # all_top_edge_keys[ssi : (esi + 2)] if 0 == ssi else all_top_edge_keys[(ssi + 1) : (esi + 1)] + # ) + # slice_top_move_values = top_move_values[ssi : (esi + 1)] + + # if len(slice_top_move_values) < 2: + # # diff縺悟叙繧後↑縺縺上i縺蟆上&縺縺ョ縺ッ辟。隕 + # logger.debug( + # f"SKIP ssi[{ssi}], esi[{esi}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" + # ) + # continue + + # sliced_diff = np.mean(np.abs(np.diff(slice_top_move_values))) + + # if sliced_diff <= horizonal_threshold: + # # 蜷御ク譁ケ蜷代ョ蛯セ縺阪↓螟牙喧縺悟ー上&縺代l縺ー縲∵ーエ蟷ウ譁ケ蜷 + # horizonal_top_edge_keys.extend(target_all_top_edge_keys) + + # logger.debug( + # f"HOR ssi[{ssi}], esi[{esi}], th[{horizonal_threshold}], sd[{sliced_diff}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" + # ) + # else: + # # 蜷御ク譁ケ蜷代ョ蛯セ縺阪↓螟牙喧縺後≠繧後ー縲∝桙逶エ譁ケ蜷 + # vertical_top_edge_keys.extend(target_all_top_edge_keys) + + # logger.debug( + # f"VER ssi[{ssi}], esi[{esi}], th[{horizonal_threshold}], sd[{sliced_diff}], edge[{[(ed, virtual_vertices[ed].vidxs()) for ed in target_all_top_edge_keys]}]" + # ) + + # if horizonal_top_edge_keys[0] == horizonal_top_edge_keys[-1]: + # del horizonal_top_edge_keys[-1] logger.debug(f"horizonal[{horizonal_top_edge_keys}]") - logger.debug(f"vertical[{vertical_top_edge_keys}]") + # logger.debug(f"vertical[{vertical_top_edge_keys}]") if not horizonal_top_edge_keys: logger.warning( "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳企Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", decoration=MLogger.DECORATION_BOX, ) - return None, None, None, None, None + return None, None, None, None, None, None, None logger.info( "-- %s: 荳企Κ繧ィ繝繧ク %s", @@ -5238,47 +7009,87 @@ def create_vertex_map( [(ek, virtual_vertices[ek].vidxs()) for ek in horizonal_top_edge_keys], ) + top_edge_poses = [] + for key in horizonal_top_edge_keys: + top_edge_poses.append(virtual_vertices[key].position().data()) + # bottom縺ッ繧ィ繝繧ク縺悟縺九l縺ヲ縺溘i蛻縺代k all_bottom_edge_keys = [] - for n, (edge_lines, edge_poses, target_dots) in enumerate( - zip(all_edge_lines, all_edge_poses, target_diff_dots) - ): - if edge_lines == horizonal_top_edge_keys: + # 鬆らせ繝槭ャ繝嶺ク企Κ縺ョ菴咲スョ + top_vv_poses = np.array([virtual_vertices[tk].position().data() for tk in horizonal_top_edge_keys]) + + # 髮「繧後◆隧穂セ。霆ク + axis_root_val = base_vertical_axis.data()[np.where(np.abs(base_vertical_axis.data()))][0] * 100 + + for n, edge_lines in enumerate(all_edge_lines): + bottom_edge_lines = [el for el in edge_lines if el not in horizonal_top_edge_keys] + + if not bottom_edge_lines: + # 蜈ィ驛ィ荳企Κ繧ィ繝繧ク縺ョ蝣エ蜷医√せ繝ォ繝シ continue - # if param_option["direction"] in [logger.transtext("荳"), logger.transtext("荳")]: - # edge_distances = np.linalg.norm((np.array(edge_poses) - parent_bone.position.data()), ord=2, axis=1) - # else: - edge_distances = np.linalg.norm((np.array(edge_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1) - edge_mean_distance = np.mean(edge_distances) - - if np.array(edge_lines)[edge_distances > mean_distance].shape[0] > 0: - # 霍晞屬縺悟ィ菴薙ョ霍晞屬繧医j驕縺蝣エ蜷医∽ク矩Κ縺ィ縺ソ縺ェ縺 - # bottom 縺ッ繧ケ繝ェ繝繝医ョ蜿ッ閭ス諤ァ縺後≠繧九ョ縺ァ縲∽クュ螟ョ蛟、縺ァ縺輔i縺ォ蛹コ蛻縺代☆繧 - distance_idxs = np.where(edge_distances > mean_distance)[0] - if np.where(np.diff(distance_idxs) > 1)[0].shape[0] > 0: - idxs = ( - [0] + [t[0] for t in np.where(np.abs(np.diff(distance_idxs)) > 1)] + [len(distance_idxs) - 1] + if bottom_edge_lines[0] == bottom_edge_lines[-1]: + del bottom_edge_lines[-1] + + target_bottom_lines = [] + for v_key in bottom_edge_lines: + vv = virtual_vertices[v_key] + + # 莉ョ諠ウ鬆らせ縺ョ隧穂セ。霆ク菴咲スョ + vv_axis_val = vv.position().data()[np.where(np.abs(base_vertical_axis.data()))][0] + + # 鬆らせ繝槭ャ繝嶺ク企Κ縺ィ縺ョ霍晞屬 + top_distances = np.linalg.norm((top_vv_poses - vv.position().data()), ord=2, axis=1) + nearest_top_vidxs = virtual_vertices[horizonal_top_edge_keys[np.argmin(top_distances)]].vidxs() + nearest_top_pos = top_vv_poses[np.argmin(top_distances)] + # 鬆らせ繝槭ャ繝嶺ク企Κ逶エ霑鷹らせ縺ョ隧穂セ。霆ク菴咲スョ + nearest_top_axis_val = nearest_top_pos[np.where(np.abs(base_vertical_axis.data()))][0] + + if (axis_root_val - nearest_top_axis_val) <= (axis_root_val - vv_axis_val): + # 隧穂セ。霆ク縺ォTOP繧医j驕縺シ医せ繧ォ繝シ繝医ョ蝣エ蜷医ゝOP繧医j荳具シ峨ョ蝣エ蜷医∝ッセ雎。 + logger.debug( + f"笳倶ク矩Κ繧ィ繝繧ク蟇セ雎。: target [{vv.vidxs()}], axis_root_val [{round(axis_root_val, 3)}], nearest_top_vidxs[{nearest_top_vidxs}], nearest_top_axis_val[{round(nearest_top_axis_val, 3)}], vv[{vv.vidxs()}], vv_axis_val[{round(vv_axis_val, 3)}]" ) - else: - idxs = [0, len(distance_idxs) - 1] + target_bottom_lines.append(v_key) - for i, (sidx, eidx) in enumerate(zip(idxs, idxs[1:])): - is_registed = False - for idx in range(sidx + (0 if i == 0 else 1), eidx + 1): - if edge_lines[distance_idxs[idx]] not in horizonal_top_edge_keys: - if not is_registed: - all_bottom_edge_keys.append([]) - is_registed = True - all_bottom_edge_keys[-1].append(edge_lines[distance_idxs[idx]]) + if target_bottom_lines: + all_bottom_edge_keys.append(target_bottom_lines) + + # if is_material_horizonal: + # # 譚占ウェ縺梧ーエ蟷ウ縺ョ蝣エ蜷 + # edge_distances = np.linalg.norm( + # (np.array(edge_poses) - np.mean(all_mean_poses, axis=0)), ord=2, axis=1 + # ) + # else: + # edge_distances = np.abs(np.array(edge_poses)[:, target_idx] - all_root_val) + + # if np.array(edge_lines)[edge_distances > all_mean_distance].shape[0] > 0: + # # 荳企Κ繧ィ繝繧ク縺九i縺ョ霍晞屬縺悟ィ菴薙ョ霍晞屬/2繧医j驕縺蝣エ蜷医∽ク矩Κ縺ィ縺ソ縺ェ縺 + # # bottom 縺ッ繧ケ繝ェ繝繝医ョ蜿ッ閭ス諤ァ縺後≠繧九ョ縺ァ縲∽クュ螟ョ蛟、縺ァ縺輔i縺ォ蛹コ蛻縺代☆繧 + # distance_idxs = np.where(edge_distances > all_mean_distance)[0] + # if np.where(np.diff(distance_idxs) > 1)[0].shape[0] > 0: + # idxs = ( + # [0] + [t for t in np.where(np.diff(distance_idxs) > 1)][0].tolist() + [len(distance_idxs) - 1] + # ) + # else: + # idxs = [0, len(distance_idxs) - 1] + + # for i, (sidx, eidx) in enumerate(zip(idxs, idxs[1:])): + # is_registed = False + # for idx in range(sidx + (0 if i == 0 else 1), eidx + 1): + # if edge_lines[distance_idxs[idx]] not in horizonal_top_edge_keys: + # if not is_registed: + # all_bottom_edge_keys.append([]) + # is_registed = True + # all_bottom_edge_keys[-1].append(edge_lines[distance_idxs[idx]]) if not all_bottom_edge_keys: logger.warning( "迚ゥ逅譁ケ蜷代↓蟇セ縺励※荳矩Κ繧ィ繝繧ク縺瑚ヲ九▽縺代i繧後↑縺九▲縺溽ぜ縲∝ヲ逅繧堤オゆコ縺励∪縺吶\nVRoid陬ス繧ケ繧ォ繝シ繝医ョ蝣エ蜷医∽ク企Κ縺ョ繝吶Ν繝磯Κ蛻縺悟性縺セ繧後※縺縺ェ縺縺九#遒コ隱阪¥縺縺輔>縲", decoration=MLogger.DECORATION_BOX, ) - return None, None, None, None, None + return None, None, None, None, None, None, None for ei, eks in enumerate(all_bottom_edge_keys): logger.info( @@ -5288,14 +7099,8 @@ def create_vertex_map( [(ek, virtual_vertices[ek].vidxs()) for ek in eks], ) - top_edge_poses = [] - for key in horizonal_top_edge_keys: - top_edge_poses.append(virtual_vertices[key].position().data()) - top_edge_mean_pos = MVector3D(np.mean(top_edge_poses, axis=0)) - top_edge_start_pos = MVector3D( - 0, 0, MVector3D(top_edge_mean_pos * np.abs(base_vertical_axis.data())).length() - ) + MVector3D(top_edge_mean_pos * np.abs(base_vertical_axis.data())) + top_edge_start_pos = top_edge_mean_pos + MVector3D(0, 0, 20) top_degrees = {} for top_pos in top_edge_poses: @@ -5314,11 +7119,9 @@ def create_vertex_map( for key in bottom_edge_keys: bottom_edge_poses.append(virtual_vertices[key].position().data()) - bottom_edge_mean_pos = MVector3D(np.mean(bottom_edge_poses, axis=0)) - # 荳ュ螟ョ縺九i逵溷セ後m - bottom_edge_start_pos = MVector3D( - 0, 0, MVector3D(bottom_edge_mean_pos * np.abs(base_vertical_axis.data())).length() - ) + MVector3D(bottom_edge_mean_pos * np.abs(base_vertical_axis.data())) + # 荳狗ォッ縺ョ荳ュ螟ョ縺ッ荳企Κ縺ォ蜷医o縺帙k + bottom_edge_mean_pos = top_edge_mean_pos.copy() + bottom_edge_start_pos = bottom_edge_mean_pos + MVector3D(0, 0, 20) # 縺ァ縺阪k縺縺題ゥ穂セ。霆ク縺ッ髮「縺励※逋サ骭イ縺吶k if param_option["direction"] in [logger.transtext("荳")]: @@ -5349,6 +7152,10 @@ def create_vertex_map( bottom_y_radius = np.max(np.abs(np.array(bottom_edge_poses)[:, 1] - bottom_edge_mean_pos.data()[1])) bottom_z_radius = np.max(np.abs(np.array(bottom_edge_poses)[:, 2] - bottom_edge_mean_pos.data()[2])) + # 隧穂セ。霆ク縺ョ蟷ウ蝮蛟、 + top_mean_val = np.mean(np.array(top_edge_poses)[:, target_idx]) + bottom_mean_val = np.mean(np.array(bottom_edge_poses)[:, target_idx]) + logger.info( "%s: 繧ィ繝繧ク荳企Κ 荳ュ螟ョ菴咲スョ[%s] 蜊雁セЪx: %s, y: %s, z: %s]", material_name, @@ -5379,21 +7186,32 @@ def create_vertex_map( if param_option["route_estimate_type"] == logger.transtext("邵ョ蟆コ"): # 荳ュ蠢縺九i隕九◆蜃ヲ逅蟇セ雎。莉ョ諠ウ鬆らせ縺ョ菴咲スョ bottom_local_pos = (bottom_target_pos - bottom_edge_mean_pos) * base_reverse_axis + bottom_radius_vec = bottom_local_pos.copy() + bottom_radius_vec.abs() + bottom_radius_vec.one() # 荳企Κ縺ョ逅諠ウ菴咲スョ繧偵*縺」縺上j豈皮紫縺九i豎ゅa縺ヲ縺翫¥ - top_ideal_pos = top_edge_mean_pos + ( + top_target_pos = top_edge_mean_pos + ( bottom_local_pos + # 蜈ィ菴薙ョ邵ョ蟆コ * ( np.array([top_x_radius, top_y_radius, top_z_radius]) / np.array([bottom_x_radius, bottom_y_radius, bottom_z_radius]) ) + # 荳狗ォッ繧ィ繝繧ク縺ョ荳翫ョ譁ケ繧貞ー上&繧√↓蛻、螳 + * abs( + abs(top_mean_val - bottom_target_pos.data()[target_idx]) + / abs(top_mean_val - bottom_mean_val) + ) ) - top_distances = np.linalg.norm((np.array(top_edge_poses) - top_ideal_pos.data()), ord=2, axis=1) - top_target_pos = MVector3D(np.array(top_edge_poses)[np.argmin(top_distances)]) + top_distances = np.linalg.norm((np.array(top_edge_poses) - top_target_pos.data()), ord=2, axis=1) + top_nearest_pos = MVector3D(np.array(top_edge_poses)[np.argmin(top_distances)]) logger.debug( - f"笳荳企Κ邵ョ蟆コ謗ィ螳: top_vidxs: [{virtual_vertices[top_target_pos.to_key(threshold)].vidxs()}, bottom_vidxs: [{virtual_vertices[bottom_key].vidxs()}], top_ideal_pos: [{top_ideal_pos.to_log()}], top_target_pos: [{top_target_pos.to_log()}]" + f"笳荳企Κ邵ョ蟆コ謗ィ螳: bottom_vidxs: [{virtual_vertices[bottom_key].vidxs()}], top_vidxs: [{virtual_vertices[top_nearest_pos.to_key(threshold)].vidxs()}, top_target_pos: [{top_target_pos.to_log()}], top_nearest_pos: [{top_nearest_pos.to_log()}]" ) - else: + elif param_option["route_estimate_type"] == logger.transtext("隗貞コヲ"): # 荳矩Κ縺ョ隗貞コヲ縺ォ鬘樔シシ縺励◆荳企Κ隗貞コヲ繧帝∈縺カ + bottom_edge_start_pos.setY(bottom_target_pos.y()) + bottom_edge_mean_pos.setY(bottom_target_pos.y()) bottom_degree0, bottom_degree1 = self.calc_arc_degree( bottom_edge_start_pos, bottom_edge_mean_pos, @@ -5405,16 +7223,21 @@ def create_vertex_map( degree_diffs0 = np.abs(np.array(list(top_degrees.keys())) - bottom_degree0) degree_diffs1 = np.abs(np.array(list(top_degrees.keys())) - bottom_degree1) - if np.min(degree_diffs0) < np.min(degree_diffs1): + if np.min(degree_diffs0) <= np.min(degree_diffs1): + bottom_degree = bottom_degree0 top_target_pos = np.array(list(top_degrees.values()))[np.argmin(degree_diffs0)] top_degree = np.array(list(top_degrees.keys()))[np.argmin(degree_diffs0)] else: + bottom_degree = bottom_degree1 top_target_pos = np.array(list(top_degrees.values()))[np.argmin(degree_diffs1)] top_degree = np.array(list(top_degrees.keys()))[np.argmin(degree_diffs1)] logger.debug( - f"笳荳企Κ隗貞コヲ謗ィ螳: top_vidxs: [{virtual_vertices[top_target_pos.to_key(threshold)].vidxs()}], bottom_vidxs: [{virtual_vertices[bottom_key].vidxs()}], bottom_degree: [{round(bottom_degree0, 3)}], nearest_top_degree: [{round(top_degree, 3)}], top_pos: [{top_target_pos.to_log()}]" + f"笳荳企Κ隗貞コヲ謗ィ螳: bottom_vidxs: [{virtual_vertices[bottom_key].vidxs()}], top_vidxs: [{virtual_vertices[top_target_pos.to_key(threshold)].vidxs()}], bottom_degree: [{round(bottom_degree, 3)}], nearest_top_degree: [{round(top_degree, 3)}], top_pos: [{top_target_pos.to_log()}]" ) + else: + # 蜿榊ッセ譁ケ蜷代↓縺セ縺」縺吶$莨ク縺ー縺 + top_target_pos = bottom_target_pos + (base_vertical_axis * 3 * -1) vkeys, vscores = self.create_vertex_line_map( bottom_key, @@ -5422,7 +7245,7 @@ def create_vertex_map( bottom_key, horizonal_top_edge_keys, virtual_vertices, - base_vertical_axis, + (base_vertical_axis * -1), [bottom_key], [], param_option, @@ -5444,7 +7267,7 @@ def create_vertex_map( material_name, f"{(ti + 1):03d}", virtual_vertices[vkeys[0]].vidxs() if vkeys else "NG", - virtual_vertices[vkeys[-1]].vidxs(), + virtual_vertices[vkeys[-1]].vidxs() if vkeys else "NG", round(score, 4) if vscores else "-", ) if len(vkeys) > 1: @@ -5461,10 +7284,10 @@ def create_vertex_map( # 蟄伜惠縺励↑縺鬆らせINDEX縺ァ莠梧ャ。蜈驟榊怜晄悄蛹 tmp_vertex_map = np.full((len(yu) * 2, len(xu), 3), (np.nan, np.nan, np.nan)) - tmp_score_map = np.full(len(xu), 0.0, dtype=np.float) + # tmp_score_map = np.full(len(xu), 0.0, dtype=np.float) registed_vertices = [] - xx = 0 + # xx = 0 # prev_vkeys = None # prev_y_offset = 0 for x, (vkeys, score) in enumerate(zip(all_vkeys, mean_scores)): @@ -5478,7 +7301,7 @@ def create_vertex_map( is_regists[y] = False if not np.count_nonzero(is_regists): - # 逋サ骭イ蟇セ雎。螟悶ョ蝣エ蜷医√せ繝ォ繝シ + # 縺吶∋縺ヲ縺ョ繧ュ繝シ縺御サ悶ョ繝ゥ繧、繝ウ縺ァ逋サ骭イ縺輔l縺ヲ縺繧句エ蜷医∫匳骭イ蟇セ雎。螟悶ョ蝣エ蜷医√せ繝ォ繝シ continue # # 譬ケ蜈縺卦OP縺ォ譚・繧九h縺縺ォ繧ェ繝輔そ繝繝医r險ュ螳 @@ -5539,17 +7362,17 @@ def create_vertex_map( if not vv.vidxs(): continue - logger.debug(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") + logger.test(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") - tmp_vertex_map[y, xx] = vkey + tmp_vertex_map[y, x] = vkey registed_vertices.append(vkey) - tmp_score_map[xx] = score + # tmp_score_map[xx] = score - xx += 1 + # xx += 1 # prev_vkeys = vkeys # prev_y_offset = y_offset - logger.debug("-------") + logger.test("-------") logger.info("%s: 鬆らせ繝槭ャ繝夕%s]: 荳崎ヲ∬サク蜑企勁", material_name, f"{(bi + 1):03d}") @@ -5561,7 +7384,7 @@ def create_vertex_map( remove_xidxs.append(v_xidx) tmp_vertex_map = np.delete(tmp_vertex_map, remove_xidxs, axis=1) - tmp_score_map = np.delete(tmp_score_map, remove_xidxs, axis=0) + # tmp_score_map = np.delete(tmp_score_map, remove_xidxs, axis=0) # Y霆ク譁ケ蜷代ョ蜑企勁 remove_yidxs = [] @@ -5587,16 +7410,10 @@ def create_vertex_map( logger.info("%s: 鬆らせ繝槭ャ繝夕%s]: 繝槭ャ繝礼函謌", material_name, f"{(bi + 1):03d}") - # XY縺ョ譛螟ァ縺ィ譛蟆上ョ謚ス蜃コ - xu = np.unique([i for i in range(tmp_vertex_map.shape[1])]) - # 蟄伜惠縺励↑縺鬆らせINDEX縺ァ莠梧ャ。蜈驟榊怜晄悄蛹 - vertex_map = np.full((tmp_vertex_map.shape[0], len(xu), 3), (np.nan, np.nan, np.nan)) - vertex_display_map = np.full((tmp_vertex_map.shape[0], len(xu)), "None ") - registed_vertices = [] + vertex_map = np.full((tmp_vertex_map.shape[0], tmp_vertex_map.shape[1], 3), (np.nan, np.nan, np.nan)) + vertex_display_map = np.full((tmp_vertex_map.shape[0], tmp_vertex_map.shape[1]), "None ") - prev_xx = 0 - xx = 0 for x in range(tmp_vertex_map.shape[1]): for y, vkey in enumerate(tmp_vertex_map[:, x]): if np.isnan(vkey).any(): @@ -5604,20 +7421,14 @@ def create_vertex_map( vkey = tuple(vkey) vv = virtual_vertices[vkey] if not vv.vidxs(): - prev_xx = xx continue - logger.debug(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") - - vertex_map[y, xx] = vkey - registed_vkeys.append(vkey) - vertex_display_map[y, xx] = ":".join([str(v) for v in vv.vidxs()]) - registed_vertices.append(vkey) + logger.test(f"x: {x}, y: {y}, vv: {vkey}, vidxs: {vv.vidxs()}") - prev_xx = xx + vertex_map[y, x] = vkey + vertex_display_map[y, x] = ":".join([str(v) for v in vv.vidxs()]) - xx += 1 - logger.debug("-------") + logger.test("-------") if vertex_map.any(): target_vertex_maps = {} @@ -5747,7 +7558,11 @@ def create_vertex_map( # 繝懊シ繝ウ騾イ陦梧婿蜷(x) x_direction_pos = (above_above_vv.position() - above_vv.position()).normalized() # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(y) - y_direction_pos = MVector3D(1, 0, 0) + y_direction_pos = ( + MVector3D(0, 0, -1) * x_direction_pos.x() + if np.isclose(abs(x_direction_pos.x()), 1) + else MVector3D(1, 0, 0) + ) # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(z) z_direction_pos = MVector3D.crossProduct(x_direction_pos, y_direction_pos) above_qq = MQuaternion.fromDirection(z_direction_pos, x_direction_pos) @@ -5769,25 +7584,47 @@ def create_vertex_map( virtual_vertices[target_key].positions.append(target_position.data()) target_vertex_map[v_yidx, v_xidx] = target_key - vertex_maps[len(vertex_maps)] = target_vertex_map + # 譛荳企Κ縺悟酔縺倥く繝シ縺ァ謠縺」縺ヲ繧紀NDEX + same_top_keys = np.where(np.sum(np.abs(np.diff(target_vertex_map[:1], axis=1)), axis=2) == 0) + separated_vertex_maps = [] + separated_vertex_display_maps = [] + if same_top_keys[1].any(): + prev_v_xidx = 0 + for v_xidx in same_top_keys[1]: + separated_vertex_maps.append(target_vertex_map[:, prev_v_xidx : (v_xidx + 1)]) + separated_vertex_display_maps.append( + target_vertex_display_map[:, prev_v_xidx : (v_xidx + 1)] + ) + prev_v_xidx = v_xidx + 1 + separated_vertex_maps.append(target_vertex_map[:, prev_v_xidx:]) + separated_vertex_display_maps.append(target_vertex_display_map[:, prev_v_xidx:]) + else: + separated_vertex_maps.append(target_vertex_map) + separated_vertex_display_maps.append(target_vertex_display_map) - logger.info("-----------------------") - logger.info("%s: 鬆らせ繝槭ャ繝夕%s]: 繝槭ャ繝礼函謌 ------", material_name, f"{len(vertex_maps):03d}") - logger.info( - "\n".join( - [ - ", ".join(target_vertex_display_map[vx, :]) - for vx in range(target_vertex_display_map.shape[0]) - ] - ), - translate=False, - ) + for (sv_map, svd_map) in zip(separated_vertex_maps, separated_vertex_display_maps): + vertex_maps[len(vertex_maps)] = sv_map + + logger.info("-----------------------") + logger.info("%s: 鬆らせ繝槭ャ繝夕%s]: 繝槭ャ繝礼函謌 ------", material_name, f"{len(vertex_maps):03d}") + logger.info( + "\n".join([", ".join(svd_map[vx, :]) for vx in range(svd_map.shape[0])]), + translate=False, + ) logger.info("%s: 鬆らせ繝槭ャ繝夕%s]: 邨ゆコ ---------", material_name, f"{(bi + 1):03d}") logger.debug("-----------------------") - return vertex_maps, virtual_vertices, remaining_vertices, back_vertices, threshold + return ( + vertex_maps, + virtual_vertices, + remaining_vertices, + back_vertices, + threshold, + is_material_horizonal, + horizonal_top_edge_keys, + ) def create_vertex_line_map( self, @@ -5796,7 +7633,7 @@ def create_vertex_line_map( from_key: tuple, top_edge_keys: list, virtual_vertices: dict, - base_vertical_axis: MVector3D, + base_vertical_reverse_axis: MVector3D, vkeys: list, vscores: list, param_option: dict, @@ -5811,86 +7648,68 @@ def create_vertex_line_map( from_pos = from_vv.position() bottom_vv = virtual_vertices[bottom_key] - bottom_pos = bottom_vv.position() - - local_next_base_pos = MVector3D(1, 0, 0) # 繝懊シ繝ウ騾イ陦梧婿蜷(x) - top_x_pos = (top_pos - bottom_pos).normalized() + top_x_pos = (top_pos - from_pos).normalized() # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(y) top_y_pos = MVector3D(1, 0, 0) + if np.isclose(abs(top_x_pos.x()), 1): + # 縺。繧縺縺ゥ豌エ蟷ウ縺ァ逵滓ィェ縺ォ蜷代°縺」縺ヲ繧句エ蜷医∫クヲ霆ク繧貞挨縺ォ險ュ螳壹☆繧 + top_y_pos = MVector3D(0, 0, -1) # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(z) top_z_pos = MVector3D.crossProduct(top_x_pos, top_y_pos) - top_qq = MQuaternion.fromDirection(top_z_pos, top_y_pos) + top_qq = MQuaternion.fromDirection(top_z_pos, top_x_pos) logger.debug( - f" - top({bottom_vv.vidxs()}): x[{top_x_pos.to_log()}], y[{top_y_pos.to_log()}], z[{top_z_pos.to_log()}]" + f" - bottom({bottom_vv.vidxs()}): top[{top_pos.to_log()}], x[{top_x_pos.to_log()}], y[{top_y_pos.to_log()}], z[{top_z_pos.to_log()}]" ) + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(from_pos) + mat.rotate(top_qq) + + local_top_vpos = (mat.inverted() * top_pos).normalized() + scores = [] - prev_dots = [] for n, to_key in enumerate(from_vv.connected_vvs): if to_key not in virtual_vertices: + # 蟄伜惠縺励↑縺繧ュ繝シ縺ッ辟。隕 scores.append(0) - prev_dots.append(0) logger.debug(f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_key}], 蟇セ雎。螟") continue if to_key in registed_vkeys: + # 逋サ骭イ貂医∩縺ョ縺ッ辟。隕厄シ磯&縺蛻励ッ蜿らァ縺励↑縺シ scores.append(0) - prev_dots.append(0) logger.debug(f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_key}], 逋サ骭イ貂医∩") continue to_vv = virtual_vertices[to_key] to_pos = to_vv.position() - direction_dot = MVector3D.dotProduct(top_x_pos, (to_pos - from_pos).normalized()) + local_next_vpos = (mat.inverted() * to_pos).normalized() + direction_dot = MVector3D.dotProduct(local_top_vpos, local_next_vpos) if to_key in vkeys: # 蛻ー驕疲ク医∩縺ョ繝吶け繝医Ν縺ォ縺ッ陦後°縺帙↑縺 scores.append(0) - prev_dots.append(0) logger.debug( - f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蛻ー驕疲ク医∩" + f" - テ揚et_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蛻ー驕疲ク医∩" ) continue - if direction_dot < 0.3: + if direction_dot < 0.2: # 蜿榊ッセ譁ケ蜷代ョ繝吶け繝医Ν縺ォ縺ッ陦後°縺帙↑縺 scores.append(0) - prev_dots.append(0) logger.debug( - f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蜿榊ッセ譁ケ蜷" + f" - テ揚et_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], 蜿榊ッセ譁ケ蜷" ) continue - mat = MMatrix4x4() - mat.setToIdentity() - mat.translate(from_pos) - mat.rotate(top_qq) - - local_next_vpos = (mat.inverted() * to_pos).normalized() - - vec_yaw1 = (local_next_base_pos * MVector3D(1, 0, 1)).normalized() - vec_yaw2 = (local_next_vpos * MVector3D(1, 0, 1)).normalized() - yaw_score = calc_ratio(MVector3D.dotProduct(vec_yaw1, vec_yaw2), -1, 1, 0, 1) - - vec_pitch1 = (local_next_base_pos * MVector3D(0, 1, 1)).normalized() - vec_pitch2 = (local_next_vpos * MVector3D(0, 1, 1)).normalized() - pitch_score = calc_ratio(MVector3D.dotProduct(vec_pitch1, vec_pitch2), -1, 1, 0, 1) - - vec_roll1 = (local_next_base_pos * MVector3D(1, 1, 0)).normalized() - vec_roll2 = (local_next_vpos * MVector3D(1, 1, 0)).normalized() - roll_score = calc_ratio(MVector3D.dotProduct(vec_roll1, vec_roll2), -1, 1, 0, 1) - - # if direction_dot < 1 and yaw_score < 0.5: - # # 繧コ繝ャ縺滓婿蜷代↓縺ッ陦後°縺帙↑縺 - # scores.append(0) - # prev_dots.append(0) - # logger.debug( - # f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}, 繧コ繝ャ譁ケ蜷" - # ) - # continue + # 繝ュ繝シ繧ォ繝ォ霆ク縺ョ蜷代″縺悟コ譚・繧九□縺禅OP縺ョ蜷代″縺ォ豐ソ縺」縺ヲ縺繧 + yaw_score = 1 - (MVector3D(local_top_vpos.x(), 0, 0) - MVector3D(local_next_vpos.x(), 0, 0)).length() + pitch_score = 1 - (MVector3D(local_top_vpos.y(), 0, 0) - MVector3D(local_next_vpos.y(), 0, 0)).length() + roll_score = 1 - (MVector3D(local_top_vpos.z(), 0, 0) - MVector3D(local_next_vpos.z(), 0, 0)).length() if param_option["route_search_type"] == logger.transtext("蜑埼らせ蜆ェ蜈"): # 蜑埼らせ縺ィ縺ョ蜀遨榊キョ繧定諷ョ縺吶k蝣エ蜷 @@ -5902,27 +7721,18 @@ def create_vertex_line_map( if len(vkeys) > 1 else 1 ) - - if prev_dot < 0.5: - # 繧コ繝ャ縺滓婿蜷代↓縺ッ陦後°縺帙↑縺 - scores.append(0) - prev_dots.append(0) - logger.debug( - f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}, 蜑阪ぜ繝ャ譁ケ蜷" - ) - continue else: # 譬ケ蜈鬆らせ縺ョ蜷代″縺ョ縺ソ蜿らァ縺吶k蝣エ蜷 prev_dot = 1 - score = (yaw_score * 20) + pitch_score + (roll_score * 2) + score = (yaw_score) * (pitch_score**3) * (roll_score**2) - # scores.append(score * (2 if to_key in top_keys else 1)) - scores.append(score) - prev_dots.append(prev_dot * direction_dot) + scores.append((score**2) * (direction_dot**3) * (prev_dot**5)) logger.debug( - f" - get_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], direction_dot[{direction_dot}], prev_dot[{prev_dot}], local_next_vpos[{local_next_vpos.to_log()}], score: [{score}], yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}" + f" - 笳吉et_vertical_key({n}): from[{from_vv.vidxs()}], to[{to_vv.vidxs()}], local_top_vpos[{local_top_vpos.to_log()}], local_next_vpos[{local_next_vpos.to_log()}]" + + f", direction_dot[{round(direction_dot, 5)}], prev_dot[{round(prev_dot, 5)}], total_score: [{round(score * direction_dot * prev_dot, 5)}], score: [{round(score, 5)}]" + + f", yaw_score: {round(yaw_score, 5)}, pitch_score: {round(pitch_score, 5)}, roll_score: {round(roll_score, 5)}" ) if np.count_nonzero(scores) == 0: @@ -5930,7 +7740,7 @@ def create_vertex_line_map( return vkeys, vscores # 譛繧ゅせ繧ウ繧「縺ョ鬮倥>INDEX繧呈治逕ィ - nearest_idx = np.argmax(np.array(scores) * np.array(prev_dots)) + nearest_idx = np.argmax(scores) vertical_key = from_vv.connected_vvs[nearest_idx] # 蜑阪ョ霎コ縺ィ縺ョ蜀遨榊キョ繧定諷ョ縺吶kシ医励Μ繝シ繝繝ゥ繧、繝ウ驕ク謚樒畑シ @@ -5944,7 +7754,7 @@ def create_vertex_line_map( ) logger.debug( - f"direction: from: [{virtual_vertices[from_key].vidxs()}], to: [{virtual_vertices[vertical_key].vidxs()}], prev_diff_dot[{round(prev_diff_dot, 4)}]" + f"笳direction: from: [{virtual_vertices[from_key].vidxs()}], to: [{virtual_vertices[vertical_key].vidxs()}], prev_diff_dot[{round(prev_diff_dot, 4)}]" ) vkeys.insert(0, vertical_key) @@ -5954,13 +7764,43 @@ def create_vertex_line_map( # 荳顔ォッ縺ォ霎ソ繧顔捩縺縺溘i邨ゆコ return vkeys, vscores + # 荳企Κ繧呈アゅa逶エ縺 + if param_option["route_estimate_type"] == logger.transtext("霆ク譁ケ蜷") or param_option[ + "route_search_type" + ] == logger.transtext("蜑埼らせ蜆ェ蜈"): + # 騾イ陦梧婿蜷代↓蜷医o縺帙※騾イ陦梧婿蜷代r讀懷コ縺吶k + # 繝懊シ繝ウ騾イ陦梧婿蜷(x) + top_x_pos = ( + virtual_vertices[vertical_key].position() - virtual_vertices[from_key].position() + ).normalized() + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ邵ヲ霆ク(y) + top_y_pos = MVector3D(1, 0, 0) + if np.isclose(abs(top_x_pos.x()), 1): + # 縺。繧縺縺ゥ豌エ蟷ウ縺ァ逵滓ィェ縺ォ蜷代°縺」縺ヲ繧句エ蜷医∫クヲ霆ク繧貞挨縺ォ險ュ螳壹☆繧 + top_y_pos = MVector3D(0, 0, -1) + # 繝懊シ繝ウ騾イ陦梧婿蜷代↓蟇セ縺励※縺ョ讓ェ霆ク(z) + top_z_pos = MVector3D.crossProduct(top_x_pos, top_y_pos) + top_qq = MQuaternion.fromDirection(top_z_pos, top_x_pos) + + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(virtual_vertices[from_key].position()) + mat.rotate(top_qq) + vertical_pos = mat.inverted() * virtual_vertices[vertical_key].position() + + mat = MMatrix4x4() + mat.setToIdentity() + mat.translate(virtual_vertices[vertical_key].position()) + mat.rotate(top_qq) + top_pos = mat * MVector3D(0, vertical_pos.y(), 0) + return self.create_vertex_line_map( bottom_key, top_pos, vertical_key, top_edge_keys, virtual_vertices, - base_vertical_axis, + base_vertical_reverse_axis, vkeys, vscores, param_option, @@ -5987,58 +7827,137 @@ def calc_arc_degree( return degree, degree + 360 def get_edge_lines( - self, edge_line_pairs: dict, start_vkey: tuple, edge_lines: list, edge_vkeys: list, param_option: dict, loop=0 + self, + edge_line_pairs: dict, + registered_edge_line_pairs: dict, + start_vkey: tuple, + edge_lines: list, + edge_vkeys: list, + virtual_vertices: dict, + param_option: dict, + loop: int, + n: int, ): - if len(edge_vkeys) >= len(edge_line_pairs.keys()) or loop > 500: - return start_vkey, edge_lines, edge_vkeys + remain_start_vkeys = [elp for elp in edge_line_pairs.keys() if edge_line_pairs[elp]] + + if not remain_start_vkeys or loop > 500: + return start_vkey, edge_lines, edge_vkeys, registered_edge_line_pairs if not start_vkey: if param_option["direction"] == logger.transtext("荳"): - # Y(譏鬆) - X(荳ュ螟ョ謠縺) - Z(髯埼) - sorted_edge_line_pairs = sorted( - list(set(edge_line_pairs.keys()) - set(edge_vkeys)), key=lambda x: (x[1], abs(x[0]), -x[2]) - ) + # X(荳ュ螟ョ謠縺) - Y(譏鬆) - Z(髯埼) + sorted_edge_line_pairs = sorted(remain_start_vkeys, key=lambda x: (abs(x[0]), x[1], -x[2])) elif param_option["direction"] == logger.transtext("蜿ウ"): - # X(髯埼) - Y(髯埼) - Z(髯埼) - sorted_edge_line_pairs = sorted( - list(set(edge_line_pairs.keys()) - set(edge_vkeys)), key=lambda x: (-x[0], -x[1], -x[2]) - ) + # Y(髯埼) - X(髯埼) - Z(髯埼) + sorted_edge_line_pairs = sorted(remain_start_vkeys, key=lambda x: (-x[1], -x[0], -x[2])) elif param_option["direction"] == logger.transtext("蟾ヲ"): - # X(譏鬆) - Y(髯埼) - Z(髯埼) - sorted_edge_line_pairs = sorted( - list(set(edge_line_pairs.keys()) - set(edge_vkeys)), key=lambda x: (x[0], -x[1], -x[2]) - ) + # Y(髯埼) - X(譏鬆) - Z(髯埼) + sorted_edge_line_pairs = sorted(remain_start_vkeys, key=lambda x: (-x[1], x[0], -x[2])) else: - # 荳: Y(髯埼) - X(荳ュ螟ョ謠縺) - Z(髯埼) - sorted_edge_line_pairs = sorted( - list(set(edge_line_pairs.keys()) - set(edge_vkeys)), key=lambda x: (-x[1], abs(x[0]), -x[2]) - ) + # 荳: X(荳ュ螟ョ謠縺) - Y(髯埼) - Z(髯埼) + sorted_edge_line_pairs = sorted(remain_start_vkeys, key=lambda x: (abs(x[0]), -x[1], -x[2])) start_vkey = sorted_edge_line_pairs[0] edge_lines.append([start_vkey]) - edge_vkeys.append(start_vkey) - if param_option["direction"] == logger.transtext("荳"): - # X(荳ュ螟ョ謠縺) - Z(髯埼) - Y(譏鬆) - sorted_edge_line_pairs = sorted(edge_line_pairs[start_vkey], key=lambda x: (abs(x[0]), -x[2], x[1])) - elif param_option["direction"] == logger.transtext("蜿ウ"): - # Y(髯埼) - Z(髯埼) - X(髯埼) - sorted_edge_line_pairs = sorted(edge_line_pairs[start_vkey], key=lambda x: (-x[1], -x[2], -x[0])) - elif param_option["direction"] == logger.transtext("蟾ヲ"): - # Y(髯埼) - Z(髯埼) - X(譏鬆) - sorted_edge_line_pairs = sorted(edge_line_pairs[start_vkey], key=lambda x: (-x[1], -x[2], x[0])) + remain_next_vkeys = list( + set( + [ + nk + for nk in edge_line_pairs[start_vkey] + if (start_vkey, nk) not in edge_vkeys and (nk, start_vkey) not in edge_vkeys + ] + ) + ) + + if not remain_next_vkeys: + if start_vkey and start_vkey in edge_line_pairs: + if start_vkey not in registered_edge_line_pairs: + registered_edge_line_pairs[start_vkey] = [] + for vk in registered_edge_line_pairs[start_vkey]: + if vk not in registered_edge_line_pairs[start_vkey]: + registered_edge_line_pairs[start_vkey].append(vk) + + del edge_line_pairs[start_vkey] + + return None, edge_lines, edge_vkeys, registered_edge_line_pairs + + if len(edge_lines[-1]) == 1: + # 蛻晏屓縺ッ繝ォ繝シ繝ォ縺ォ豐ソ縺」縺ヲ谺。繧呈歓蜃コ縺吶k + if param_option["direction"] == logger.transtext("荳"): + # X(荳ュ螟ョ謠縺) - Z(髯埼) - Y(譏鬆) + next_vkey = sorted(remain_next_vkeys, key=lambda x: (abs(x[0]), -x[2], x[1]))[0] + elif param_option["direction"] == logger.transtext("蜿ウ"): + # Y(髯埼) - Z(髯埼) - X(髯埼) + next_vkey = sorted(remain_next_vkeys, key=lambda x: (-x[1], -x[2], -x[0]))[0] + elif param_option["direction"] == logger.transtext("蟾ヲ"): + # Y(髯埼) - Z(髯埼) - X(譏鬆) + next_vkey = sorted(remain_next_vkeys, key=lambda x: (-x[1], -x[2], x[0]))[0] + else: + # 荳: X(荳ュ螟ョ謠縺) - Z(髯埼) - Y(髯埼) + next_vkey = sorted(remain_next_vkeys, key=lambda x: (abs(x[0]), -x[2], -x[1]))[0] else: - # 荳: X(荳ュ螟ョ謠縺) - Z(髯埼) - Y(髯埼) - sorted_edge_line_pairs = sorted(edge_line_pairs[start_vkey], key=lambda x: (abs(x[0]), -x[2], -x[1])) + # 2蝗樒岼莉・髯阪ッ蜃コ譚・繧九□縺大遨阪′螟ァ縺阪>縺ョ繧帝∈縺カ + next_dots = [] + for vkey in remain_next_vkeys: + next_dots.append( + MVector3D.dotProduct( + ( + virtual_vertices[edge_lines[-1][-1]].position() + - virtual_vertices[edge_lines[-1][-2]].position() + ).normalized(), + ( + virtual_vertices[vkey].position() - virtual_vertices[edge_lines[-1][-1]].position() + ).normalized(), + ) + ) + next_vkey = remain_next_vkeys[np.argmax(next_dots)] - for next_vkey in sorted_edge_line_pairs: - if next_vkey not in edge_vkeys: + if start_vkey: + if start_vkey and (start_vkey, next_vkey) not in edge_vkeys: + # 縺セ縺邨縺ソ蜷医o縺帙′逋サ骭イ縺輔l縺ヲ縺縺ェ縺蝣エ蜷医ョ縺ソ逋サ骭イ edge_lines[-1].append(next_vkey) - edge_vkeys.append(next_vkey) - start_vkey, edge_lines, edge_vkeys = self.get_edge_lines( - edge_line_pairs, next_vkey, edge_lines, edge_vkeys, param_option, loop + 1 - ) + edge_vkeys.append((start_vkey, next_vkey)) + + if start_vkey not in registered_edge_line_pairs: + registered_edge_line_pairs[start_vkey] = [] + if next_vkey not in registered_edge_line_pairs[start_vkey]: + registered_edge_line_pairs[start_vkey].append(next_vkey) + + if next_vkey not in registered_edge_line_pairs: + registered_edge_line_pairs[next_vkey] = [] + if start_vkey not in registered_edge_line_pairs[next_vkey]: + registered_edge_line_pairs[next_vkey].append(start_vkey) + + for n, nk in enumerate(edge_line_pairs[start_vkey]): + if nk == next_vkey: + del edge_line_pairs[start_vkey][n] + + for n, sk in enumerate(edge_line_pairs[next_vkey]): + if sk == start_vkey: + del edge_line_pairs[next_vkey][n] + + if start_vkey in edge_line_pairs and not edge_line_pairs[start_vkey]: + if start_vkey not in registered_edge_line_pairs: + registered_edge_line_pairs[start_vkey] = [] + for vk in registered_edge_line_pairs[start_vkey]: + if vk not in registered_edge_line_pairs[start_vkey]: + registered_edge_line_pairs[start_vkey].append(vk) + + del edge_line_pairs[start_vkey] + + _, edge_lines, edge_vkeys, registered_edge_line_pairs = self.get_edge_lines( + edge_line_pairs, + registered_edge_line_pairs, + next_vkey, + edge_lines, + edge_vkeys, + virtual_vertices, + param_option, + loop + 1, + n, + ) - return None, edge_lines, edge_vkeys + return None, edge_lines, edge_vkeys, registered_edge_line_pairs def get_rigidbody(self, model: PmxModel, bone_name: str): if bone_name not in model.bones: @@ -6067,7 +7986,7 @@ def get_block_vidxs( target_v_yidx = ( np.max(np.where(regist_bones[: (v_yidx + 1), v_xidx])) if regist_bones[: (v_yidx + 1), v_xidx].any() - else np.max(regist_bones[: (v_yidx + 1), : (v_xidx + 1)][0]) + else np.max(np.where(regist_bones[: (v_yidx + 1), : (v_xidx + 1)])[0]) if regist_bones[: (v_yidx + 1), : (v_xidx + 1)].any() else regist_bones.shape[0] - 1 ) @@ -6104,6 +8023,14 @@ def get_block_vidxs( prev_xidx = 0 prev_connected = True elif v_xidx == 0: + prev_map_idx = ( + base_map_idx + if len(all_bone_connected) == 1 + else base_map_idx - 1 + if base_map_idx > 0 + else len(all_bone_connected) - 1 + ) + prev_xidx = all_bone_connected[prev_map_idx].shape[1] - 1 if len(all_bone_connected) == 1 and all_bone_connected[base_map_idx][target_v_yidx, -1]: # 譛蠕後′蜈磯ュ縺ィ郢九′縺」縺ヲ縺繧句エ蜷医∵怙蠕後→郢九$ prev_xidx = registed_max_v_xidx @@ -6111,7 +8038,7 @@ def get_block_vidxs( prev_connected = True elif ( base_map_idx > 0 - and all_bone_connected[list(all_bone_connected.keys())[base_map_idx - 1]].shape[1] > 1 + and all_bone_connected[list(all_bone_connected.keys())[base_map_idx - 1]].shape[1] > 0 and all_bone_connected[list(all_bone_connected.keys())[base_map_idx - 1]].shape[0] > target_v_yidx and all_bone_connected[list(all_bone_connected.keys())[base_map_idx - 1]][target_v_yidx, -1].any() ): @@ -6121,7 +8048,7 @@ def get_block_vidxs( if ( tuple(vertex_maps[prev_map_idx][target_v_yidx, -1]) == tuple(vertex_maps[base_map_idx][target_v_yidx, v_xidx]) - and all_bone_connected[prev_map_idx].shape[1] > 2 + and all_bone_connected[prev_map_idx].shape[1] > 1 and all_bone_connected[prev_map_idx][target_v_yidx, -2].any() ): # 蜑阪ョ繝懊シ繝ウ縺悟酔縺倅サョ諠ウ鬆らせ縺ァ縺ゅj縲√°縺、縺昴ョ繧ゅ≧縺イ縺ィ縺、蜑阪→郢九′縺」縺ヲ縺繧句エ蜷 @@ -6145,15 +8072,13 @@ def get_block_vidxs( else 0 ) else: - # 1逡ェ逶ョ莉・髯阪ッ縲∬ェ蛻繧医j蜑阪〒縲√懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧区怙繧りソ代>縺ョ - prev_xidx = ( - np.max(np.where(regist_bones[v_yidx, :v_xidx])) - if regist_bones[v_yidx, :v_xidx].any() - else np.max(np.where(regist_bones[: (v_yidx + 1), :v_xidx])[1]) - if np.where(regist_bones[: (v_yidx + 1), :v_xidx])[1].any() - else 0 + # 蜑帑ス薙サ繧ク繝ァ繧、繝ウ繝医ョ1逡ェ逶ョ莉・髯阪ッ縲∬ェ蛻繧医j蜑阪〒縲∝酔縺伜励↓繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧区怙繧りソ代>縺ョ + prev_xidx = max( + set(np.where(regist_bones[target_v_yidx, :v_xidx])[0].tolist()) + | set(np.where(all_bone_connected[base_map_idx][target_v_yidx, :v_xidx] == 0)[0].tolist()) + | {0} ) - prev_connected = True + prev_connected = True if all_bone_connected[base_map_idx][v_yidx, prev_xidx] else False next_xidx = registed_max_v_xidx next_map_idx = base_map_idx @@ -6163,88 +8088,67 @@ def get_block_vidxs( next_xidx = regist_bones.shape[1] - 1 next_connected = True elif v_xidx >= registed_max_v_xidx: + next_map_idx = ( + base_map_idx + if len(all_bone_connected) == 1 + else base_map_idx + 1 + if base_map_idx < len(all_bone_connected) - 1 + else base_map_idx + ) + next_xidx = 0 if len(all_bone_connected) == 1 and all_bone_connected[base_map_idx][v_yidx, registed_max_v_xidx:].any(): # 譛蠕後′蜈磯ュ縺ィ郢九′縺」縺ヲ縺繧句エ蜷(譛蠕後ョ譛牙柑繝懊シ繝ウ縺九i譛蛻昴∪縺ァ縺後←縺薙°郢九′縺」縺ヲ縺繧句エ蜷茨シ峨∵怙蠕後→郢九$シ医槭ャ繝励′1縺、縺ョ蝣エ蜷茨シ - next_xidx = 0 - next_map_idx = base_map_idx next_connected = True + next_map_idx = 0 elif ( base_map_idx < len(all_bone_connected) - 1 and all_bone_connected[base_map_idx][v_yidx, registed_max_v_xidx:].any() ): # 繝槭ャ繝励′隍謨ー縲√°縺、譛蠕後〒縺ッ縺ェ縺蝣エ蜷茨シ域ャ。縺ョ蜈磯ュ縺ィ郢九$シ - next_xidx = 0 - next_map_idx = base_map_idx + 1 next_connected = True elif ( base_map_idx == len(all_bone_connected) - 1 and all_bone_connected[base_map_idx][v_yidx, registed_max_v_xidx:].any() ): # 繝槭ャ繝励′隍謨ー縺九▽譛蠕後〒縺ゅk蝣エ蜷茨シ域怙蛻昴ョ蜈磯ュ縺ィ郢九$シ - next_map_idx = 0 next_connected = True - - if ( - next_map_idx < len(vertex_maps) - and base_map_idx < len(vertex_maps) - and v_yidx < vertex_maps[next_map_idx].shape[0] - and v_yidx < vertex_maps[base_map_idx].shape[0] - and tuple(vertex_maps[next_map_idx][v_yidx, 0]) == tuple(vertex_maps[base_map_idx][v_yidx, v_xidx]) - and all_bone_connected[next_map_idx][v_yidx, 0].any() - ): - # 谺。縺ョ繝懊シ繝ウ縺悟酔縺倅サョ諠ウ鬆らせ縺ァ縺ゅj縲√°縺、縺昴ョ繧ゅ≧縺イ縺ィ縺、蜈医→郢九′縺」縺ヲ縺繧句エ蜷 - next_xidx = 1 - else: - # 谺。縺ョ繝懊シ繝ウ縺ョ莉ョ諠ウ鬆らせ縺瑚ェ蛻縺ィ驕輔≧蝣エ蜷医√◎縺ョ縺セ縺セ蜑阪ョ繧呈治逕ィ - next_xidx = 0 + next_map_idx = 0 else: - # max繧医j蜑阪ッ縲∬ェ蛻繧医j蜑阪〒縲√懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧区怙繧りソ代>縺ョ - next_xidx = ( - np.min(np.where(regist_bones[v_yidx, (v_xidx + 1) :])) + (v_xidx + 1) - if regist_bones[v_yidx, (v_xidx + 1) :].any() - else np.min(np.where(regist_bones[: (v_yidx + 1), (v_xidx + 1) :])[1]) + (v_xidx + 1) - if np.where(regist_bones[: (v_yidx + 1), (v_xidx + 1) :])[1].any() - else registed_max_v_xidx + # 蜑帑ス薙サ繧ク繝ァ繧、繝ウ繝医ョmax繧医j蜑阪ッ縲∬ェ蛻繧医j蜑阪〒縲∫クヲ蛻励ョ縺縺壹l縺九↓繝懊シ繝ウ縺檎匳骭イ縺輔l縺ヲ縺繧区怙繧りソ代>縺ョ + next_xidx = min( + set((np.where(regist_bones[target_v_yidx, (v_xidx + 1) :])[0] + (v_xidx + 1)).tolist()) + | set( + ( + np.where( + all_bone_connected[base_map_idx][ + min(all_bone_connected[base_map_idx].shape[0] - 2, target_v_yidx), (v_xidx + 1) : + ] + == 0 + )[0] + + (v_xidx + 1) + ).tolist() + ) + | {regist_bones.shape[1] - 1} ) - next_connected = True + # 閾ェ霄ォ縺九i髫」縺檎ケ九′縺」縺ヲ縺繧九° + next_connected = True if all_bone_connected[base_map_idx][v_yidx, v_xidx] else False above_yidx = 0 if v_yidx > 0: - if is_weight: - # 繧ヲ繧ァ繧、繝医ョ蝣エ蜷医ッ霑第園縺ョ繧ょ盾辣ァ - above_yidx = ( - np.max(np.where(regist_bones[:v_yidx, v_xidx])) - if regist_bones[:v_yidx, v_xidx].any() - else np.max(np.where(regist_bones[:v_yidx, :v_xidx])[0]) - if np.where(regist_bones[:v_yidx, :v_xidx])[0].any() - else 0 - ) - else: - above_yidx = ( - np.max(np.where(regist_bones[:v_yidx, v_xidx])) if regist_bones[:v_yidx, v_xidx].any() else 0 - ) - - below_yidx = np.max(np.where(vertex_map[:, v_xidx, :])[0]) - if is_weight: - # 繧ヲ繧ァ繧、繝医ョ蝣エ蜷医ッ霑第園縺ョ繧ょ盾辣ァ - below_yidx = ( - np.min(np.where(regist_bones[(v_yidx + 1) :, v_xidx])) + (v_yidx + 1) - if regist_bones[(v_yidx + 1) :, v_xidx].any() - else np.min(np.where(regist_bones[(v_yidx + 1) :, :v_xidx])[0]) + (v_yidx + 1) - if np.where(regist_bones[(v_yidx + 1) :, :v_xidx])[0].any() - else np.max(regist_bones[:, v_xidx]) - if v_yidx <= np.max(regist_bones[:, v_xidx]) - else np.max(np.where(vertex_map[:-1, v_xidx, :])[0]) - ) - else: - below_yidx = ( - np.min(np.where(regist_bones[(v_yidx + 1) :, v_xidx])) + (v_yidx + 1) - if regist_bones[(v_yidx + 1) :, v_xidx].any() - else np.max(regist_bones[:, v_xidx]) - if v_yidx <= np.max(regist_bones[:, v_xidx]) - else np.max(np.where(vertex_map[:, v_xidx, :])[0]) + # 讓ェ蛻嶺ク頑婿縺ョ縺縺壹l縺九↓逋サ骭イ縺輔l縺ヲ縺繧句エ蜷 + above_yidx = ( + np.max(np.where(regist_bones[:v_yidx, target_v_xidx])[0]) + if np.where(regist_bones[:v_yidx, target_v_xidx])[0].any() + else 0 ) + # 讓ェ蛻嶺ク区婿縺ョ縺縺壹l縺九↓逋サ骭イ縺輔l縺ヲ縺繧句エ蜷 + below_yidx = ( + np.min(np.where(regist_bones[(v_yidx + 1) :, target_v_xidx])[0]) + (v_yidx + 1) + if np.where(regist_bones[(v_yidx + 1) :, target_v_xidx])[0].any() + else registed_max_v_yidx + ) + max_v_xidx = np.max(np.where(vertex_map[v_yidx, :, :])[0]) max_v_yidx = np.max(np.where(vertex_map[:, v_xidx, :])[0]) @@ -6284,18 +8188,19 @@ def randomname(n) -> str: # t :繝吶け繝医Ν菫よ焚シ域綾繧雁、シ # 謌サ繧雁、: 譛遏ュ霍晞屬 def calc_point_line_dist(point: MPoint, line: MLine): - v_length_square = line.vector_start.lengthSquared() + v_length_square = line.vector_real.lengthSquared() t = 0.0 if v_length_square > 0.0: - t = MVector3D.dotProduct(line.vector_start.normalized(), (point - line.point).normalized()) / v_length_square + t = MVector3D.dotProduct(line.vector, (point.point - line.point.point).normalized()) / v_length_square - h = line.point + line.vector_start * t - return (h - point).length(), h, t + h = line.point.point + line.vector * t + length = (h - point.point).length() + return length, h, t # 竏p1p2p3縺ッ驪ュ隗? def is_sharp_angle(p1: MPoint, p2: MPoint, p3: MPoint): - return MVector3D.dotProduct((p1.normalized() - p2.normalized()), (p3.normalized() - p2.normalized())) > 0 + return MVector3D.dotProduct((p1.point - p2.point).normalized(), (p3.point - p2.point).normalized()) > 0 # 轤ケ縺ィ邱壼縺ョ譛遏ュ霍晞屬 @@ -6306,17 +8211,19 @@ def is_sharp_angle(p1: MPoint, p2: MPoint, p3: MPoint): # 謌サ繧雁、: 譛遏ュ霍晞屬 def calc_point_segment_dist(point: MPoint, segment: MSegment): - end_point = segment.vector_end + end_point = MPoint(segment.vector_end) # 蝙らキ壹ョ髟キ縺輔∝桙邱壹ョ雜ウ縺ョ蠎ァ讓吝所縺ウt繧堤ョ怜コ - min_length, h, t = calc_point_line_dist(point, MLine(segment.point, end_point - segment.point)) + min_length, h, t = calc_point_line_dist(point, MLine(segment.point, end_point.point - segment.point.point)) if not is_sharp_angle(point, segment.point, end_point): # 蟋狗せ蛛エ縺ョ螟門エ - return (segment.point - point).length(), segment.point, t + min_length = (segment.point.point - point.point).length() + h = segment.point.point elif not is_sharp_angle(point, end_point, segment.point): # 邨らせ蛛エ縺ョ螟門エ - return (end_point - point).length(), end_point, t + min_length = (end_point.point - point.point).length() + h = end_point.point return min_length, h, t @@ -6332,26 +8239,35 @@ def calc_point_segment_dist(point: MPoint, segment: MSegment): def calc_line_line_dist(l1: MLine, l2: MLine): # 2逶エ邱壹′蟷ウ陦鯉シ - if MVector3D.dotProduct(l1.vector_start.normalized(), l2.vector_start.normalized()) == 1: + if np.isclose(MVector3D.dotProduct(l1.vector, l2.vector), 1): # 轤ケP11縺ィ逶エ邱哭2縺ョ譛遏ュ霍晞屬縺ョ蝠城。後↓蟶ー逹 min_length, p2, t2 = calc_point_line_dist(l1.point, l2) - return min_length, l1.point, p2, 0.0, t2 + return min_length, l1.point.point, p2, 0.0, t2 # 2逶エ邱壹ッ縺ュ縺倥l髢「菫 - DV1V2 = MVector3D.dotProduct(l1.vector_start.normalized(), l2.vector_start.normalized()) - DV1V1 = l1.vector_start.lengthSquared() - DV2V2 = l2.vector_start.lengthSquared() - P21P11 = l1.point - l2.point + DV1V2 = MVector3D.dotProduct(l1.vector_real, l2.vector_real) + DV1V1 = l1.vector_real.lengthSquared() + DV2V2 = l2.vector_real.lengthSquared() + P21P11 = (l1.point.point - l2.point.point).normalized() + + if (DV1V1 * DV2V2 - DV1V2 * DV1V2) == 0: + min_length, p2, t2 = calc_point_line_dist(l1.point, l2) + return min_length, l1.point.point, p2, 0.0, t2 t1 = ( - DV1V2 * MVector3D.dotProduct(l2.vector_start.normalized(), P21P11.normalized()) - - DV2V2 * MVector3D.dotProduct(l1.vector_start.normalized(), P21P11.normalized()) + DV1V2 * MVector3D.dotProduct(l2.vector_real, P21P11) - DV2V2 * MVector3D.dotProduct(l1.vector_real, P21P11) ) / (DV1V1 * DV2V2 - DV1V2 * DV1V2) - p1 = l1.vector_start * t1 - t2 = MVector3D.dotProduct(l2.vector_start.normalized(), (p1 - l2.point).normalized()) / DV2V2 - p2 = l2.vector_start * t2 + p1 = l1.get_point(t1) + t2 = MVector3D.dotProduct(l2.vector_real, (p1 - l2.point.point)) / DV2V2 + p2 = l2.get_point(t2) + length = (p2 - p1).length() + length2 = (l1.point.point - l2.point.point).length() - return (p2 - p1).length(), p1, p2, t1, t2 + if length > length2: + # 莉ョ蟇セ蠢 + return length2, l1.point.point, l2.point.point, 0.5, 0.5 + + return length, p1, p2, t1, t2 # 2邱壼縺ョ譛遏ュ霍晞屬 @@ -6365,29 +8281,29 @@ def calc_line_line_dist(l1: MLine, l2: MLine): def calc_segment_segment_dist(s1: MSegment, s2: MSegment): # S1縺檎クョ騾縺励※縺繧具シ - if s1.vector_start.lengthSquared() < 0.00001: + if s1.vector_real.lengthSquared() < 0.00001: # S2繧らクョ騾シ - if s2.vector_start.lengthSquared() < 0.00001: + if s2.vector_real.lengthSquared() < 0.00001: # 轤ケ縺ィ轤ケ縺ョ霍晞屬縺ョ蝠城。後↓蟶ー逹 - return (s2.point - s1.point).length(), s1.point, s2.point, 0, 0 + return (s2.point.point - s1.point.point).length(), s1.point.point, s2.point.point, 0, 0 else: # S1縺ョ蟋狗せ縺ィS2縺ョ譛遏ュ蝠城。後↓蟶ー逹 min_length, p2, t2 = calc_point_segment_dist(s1.point, s2) - return min_length, s1.point, p2, 0.0, max(0, min(1, t2)) + return min_length, s1.point.point, p2, 0.0, max(0, min(1, t2)) # S2縺檎クョ騾縺励※縺繧具シ - elif s2.vector_start.lengthSquared() < 0.00001: + elif s2.vector_real.lengthSquared() < 0.00001: # S2縺ョ蟋狗せ縺ィS1縺ョ譛遏ュ蝠城。後↓蟶ー逹 - min_length, p2, t2 = calc_point_segment_dist(s2.point, s1) - return min_length, s2.point, p2, 0.0, t2 + min_length, p1, t1 = calc_point_segment_dist(s2.point, s1) + return min_length, p1, s2.point.point, max(0, min(1, t1)), 0.0 # 邱壼蜷悟」ォ ------ # 2邱壼縺悟ケウ陦後□縺」縺溘i蝙らキ壹ョ遶ッ轤ケ縺ョ荳縺、繧単1縺ォ莉ョ豎コ螳 - if MVector3D.dotProduct(s1.vector_start.normalized(), s2.vector_start.normalized()) == 1: - p1 = s1.point - t1 = 0 + if np.isclose(MVector3D.dotProduct(s1.vector, s2.vector), 1): min_length, p2, t2 = calc_point_segment_dist(s1.point, s2) + t1 = 0 + p1 = s1.point if 0 <= t2 <= 1: return min_length, p1, p2, t1, t2 else: @@ -6400,21 +8316,21 @@ def calc_segment_segment_dist(s1: MSegment, s2: MSegment): # 蝙らキ壹ョ雜ウ縺悟、悶↓縺ゅk莠九′蛻、譏 # S1蛛エ縺ョt1繧0ス1縺ョ髢薙↓繧ッ繝ゥ繝ウ繝励@縺ヲ蝙らキ壹r髯阪m縺 t1 = max(0, min(1, t1)) - p1 = s1.vector_start + s1.vector_start * t1 - min_length, p2, t2 = calc_point_segment_dist(p1, s2) + p1 = s1.get_point(t1) + min_length, p2, t2 = calc_point_segment_dist(MPoint(p1), s2) if 0 <= t2 <= 1: return min_length, p1, p2, t1, t2 # S2蛛エ縺悟、悶□縺」縺溘ョ縺ァS2蛛エ繧偵け繝ゥ繝ウ繝励ヾ1縺ォ蝙らキ壹r髯阪m縺 t2 = max(0, min(1, t2)) - p2 = s2.vector_start + s2.vector_start * t2 - min_length, p1, t1 = calc_point_segment_dist(p2, s1) + p2 = s2.get_point(t2) + min_length, p1, t1 = calc_point_segment_dist(MPoint(p2), s1) if 0 <= t1 <= 1: return min_length, p1, p2, t1, t2 # 蜿梧婿縺ョ遶ッ轤ケ縺梧怙遏ュ縺ィ蛻、譏 t1 = max(0, min(1, t1)) - p1 = s1.vector_start + s1.vector_start * t1 + p1 = s1.get_point(t1) return (p2 - p1).length(), p1, p2, t1, t2 @@ -6460,7 +8376,7 @@ def is_col_capsule_capsule(c1: MCapsule, c2: MCapsule): # def calc_intersect(P0: MVector3D, P1: MVector3D, Q0: MVector3D, Q1: MVector3D) -> MVector3D: # u = P1 - P0 -# dot = MVector3D.dotProduct(Q1.normalized(), u.normalized()) +# dot = MVector3D.dotProduct(Q1, u) # if np.isclose(dot, 0): # return None @@ -6477,7 +8393,7 @@ def is_col_capsule_capsule(c1: MCapsule, c2: MCapsule): # https://stackoverflow.com/questions/34602761/intersecting-3d-lines -def calc_intersect(P0: MVector3D, P1: MVector3D, Q0: MVector3D, Q1: MVector3D) -> MVector3D: +def calc_intersect(P0: MVector3D, P1: MVector3D, Q0: MVector3D, Q1: MVector3D) -> tuple: # Direction vectors DP = (P1 - P0).normalized() DQ = (Q1 - Q0).normalized() @@ -6539,6 +8455,32 @@ def read_vertices_from_file(file_path: str, model: PmxModel, material_name=None) return target_vertices +# area of polygon poly +def poly_area(poly): + if len(poly) < 3: # not a plane - no area + return 0 + total = [0, 0, 0] + N = len(poly) + for i in range(N): + vi1 = poly[i] + vi2 = poly[(i + 1) % N] + prod = np.cross(vi1, vi2) + total[0] += prod[0] + total[1] += prod[1] + total[2] += prod[2] + result = np.dot(total, unit_normal(poly[0], poly[1], poly[2])) + return abs(result / 2) + + +# unit normal vector of plane defined by points a, b, and c +def unit_normal(a, b, c): + x = np.linalg.det([[1, a[1], a[2]], [1, b[1], b[2]], [1, c[1], c[2]]]) + y = np.linalg.det([[a[0], 1, a[2]], [b[0], 1, b[2]], [c[0], 1, c[2]]]) + z = np.linalg.det([[a[0], a[1], 1], [b[0], b[1], 1], [c[0], c[1], 1]]) + magnitude = (x**2 + y**2 + z**2) ** 0.5 + return (x / magnitude, y / magnitude, z / magnitude) + + SEMI_STANDARD_BONE_NAMES = [ "蜈ィ縺ヲ縺ョ隕ェ", "繧サ繝ウ繧ソ繝シ", diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor - \343\202\263\343\203\263\343\203\206\343\203\263\343\203\204\343\203\204\343\203\252\343\203\274\347\224\250\351\235\231\347\224\273.url" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor - \343\202\263\343\203\263\343\203\206\343\203\263\343\203\204\343\203\204\343\203\252\343\203\274\347\224\250\351\235\231\347\224\273.url" new file mode 100644 index 0000000..cdcb083 --- /dev/null +++ "b/\351\205\215\345\270\203/v2.1.0/PmxTailor - \343\202\263\343\203\263\343\203\206\343\203\263\343\203\204\343\203\204\343\203\252\343\203\274\347\224\250\351\235\231\347\224\273.url" @@ -0,0 +1,2 @@ +[InternetShortcut] + URL=https://seiga.nicovideo.jp/seiga/im10854784 \ No newline at end of file diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe" new file mode 100644 index 0000000..19e863a Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US.lnk" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US.lnk" new file mode 100644 index 0000000..46f59e3 Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US.lnk" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US_Log.lnk" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US_Log.lnk" new file mode 100644 index 0000000..c5cc93b Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - en_US_Log.lnk" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN.lnk" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN.lnk" new file mode 100644 index 0000000..0a7250b Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN.lnk" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN_Log.lnk" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN_Log.lnk" new file mode 100644 index 0000000..991d06f Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - zh_CN_Log.lnk" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - \343\203\255\343\202\260\343\201\202\343\202\212\347\211\210.lnk" "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - \343\203\255\343\202\260\343\201\202\343\202\212\347\211\210.lnk" new file mode 100644 index 0000000..5036961 Binary files /dev/null and "b/\351\205\215\345\270\203/v2.1.0/PmxTailor_2.01.00.exe - \343\203\255\343\202\260\343\201\202\343\202\212\347\211\210.lnk" differ diff --git "a/\351\205\215\345\270\203/v2.1.0/Readme.txt" "b/\351\205\215\345\270\203/v2.1.0/Readme.txt" new file mode 100644 index 0000000..e0e1895 --- /dev/null +++ "b/\351\205\215\345\270\203/v2.1.0/Readme.txt" @@ -0,0 +1,303 @@ +---------------------------------------------------------------- +---------------------------------------------------------------- + + 「PmxTailor ローカル版」 + +  ver2.01.00 + +                 miu200521358 + +---------------------------------------------------------------- +---------------------------------------------------------------- + + + この度は拙作をDLしていただき、ありがとうございます。 + お手数ですが以下をご確認のうえ、ご利用ください。 + +---------------------------------------------------------------- + + +---------------------------------------------------------------- +■ 概要 +---------------------------------------------------------------- + + 指定した材質に任意の物理を設定するツールです。 + + 物理の設定をスライダーパラメーターで調整できます + (直接剛体等の値を調整することも可能です) + + 下記材質にも物理を割り当てる事ができます +  ・プリーツ形状の材質 +  ・複数のスリットがある材質 +  ・複雑なメッシュの材質(凸凹があるのは苦手です) +  ・裏面や厚みのある材質 + + +---------------------------------------------------------------- +■ 配布動画 +---------------------------------------------------------------- + +■ 【MMD】布っぽい物理を入れられるツールを作ってみた【ツール配布】【PmxTailor ver1.00】 +https://www.nicovideo.jp/watch/sm39696512 +https://youtu.be/yOCPhRNFE2k + +■ 【MMD】MMDでクロスシミュできるツールを簡単にしてみた【ツール配布】【PmxTailor ver2.00】 +https://www.nicovideo.jp/watch/sm40783084 +https://youtu.be/aQ70AHE8Rdo + +---------------------------------------------------------------- +■ 同梱ファイル +---------------------------------------------------------------- + + ・PmxTailor2.01.00.exe   … ツール本体(言語別ショートカットあり) + ・Readme.txt        … リドミ + ・VMDサイジングWiki     … Wikiへのリンク + ・コンテンツツリー用静画  … コンテンツツリー用静画へのリンク + + +---------------------------------------------------------------- +■ 動作環境 +---------------------------------------------------------------- + + Windows8.1/10/11 64bit(確認はWindows10のみ) + + +---------------------------------------------------------------- +■ 起動 +---------------------------------------------------------------- + +・基本的にはexeをそのまま起動していただければ大丈夫です。 + +・ログあり版は、出力VMDファイルパスと同じところにログファイルを出力します。 + +・ファイル履歴は、「history.json」をexeと同じ階層に配置する事でコピー可能です。 + + +---------------------------------------------------------------- +■ 物理設定機能の使い方 +---------------------------------------------------------------- + + 1. PmxEditor の「ファイル>PMXデータの状態検証」で「×」ステータスがないことを確認します + ・特に名称の重複などがあるとPMXの書き出しなどで失敗するリスクが大きくなります + + 2. 物理を割り当てしたいメッシュのある材質を確認します + ・材質の一部にだけ物理を割り当てたい場合、PMXEditorの「編集>リスト関係>View選択対象(複数)のリスト選択>頂点」で頂点の複数選択ができるようにしてから、 + 割り当てたい材質頂点を選択して、「右クリック>CSVファイルへ保存」でCSVに保存してください。 + ・材質を分ける場合、PMXEditorでは「編集>選択面>新規材質へ取り出し」を実行してください + + 3. PmxTailorを起動します + + 4. 対象モデルに 1. のモデルを指定します + + 5. 「パラ調整」タブで材質等を設定します + ・「物理材質」「材質略称」「親ボーン」「剛体グループ」は必須項目です + ・「物理方向」は袖など左右に物理が流れて欲しい場合などに指定して下さい + ・スライダーによる材質調整を行うと、「パラ調整(詳細)」タブ内の各パラメーターに反映されます + ・「パラ調整(詳細)」タブ内の各パラメーターを直接調整する事も可能です + (ただし「パラ調整(詳細)」パラメーターを調整しても「パラ調整」には反映されません) + ・「既存設定」を「再利用」で指定した場合、「パラ調整(ボーン)」タブでボーンの並び順を指定する事で、 + 既存のボーンとウェイトを再利用して、剛体とジョイントのみ作り直します + ・「既存設定」を「上書き」で指定した場合、ボーン・剛体・ジョイントを削除して頂点走査を行い物理を割り当てます + ・裾(ボーンの先の材質)を同じボーンに割り当てたい場合、「裾材質」に材質を指定してください + ・裏面(基本的に表と同じポリ割りの材質)を同じボーンに割り当てたい場合、「裏面材質」に材質を指定してください + ・材質の一部にだけ物理を割り当てたい場合、「対象頂点CSV」欄に 1. で保存したCSVファイルを指定してください + + 6. 「ファイル」タブの「PmxTailor実行」ボタンをクリックします + ・複数スリットはスリット単位で物理を割り当てます + ・同一材質の裾(ポリ割りが変わってる箇所)はボーンを割り当てず、上のボーンでウェイトを割り当てます + ・裾材質で指定された材質も同様に上のボーンでウェイトを割り当てます + ・裏面はほぼ同じ位置にある表材質の頂点を割り当てます + + +---------------------------------------------------------------- +■ 問題が起きた場合 +---------------------------------------------------------------- + + ・解凍ファイルの文字化け + ・マカフィーでウィルスが入っていると検知されてしまう + といった問題が起きた場合、下記ページを参照して、解決できるかご確認ください。(VMDサイジングのFAQページです) + + https://github.com/miu200521358/vmd_sizing/wiki/03.-%E5%95%8F%E9%A1%8C%E3%81%8C%E8%B5%B7%E3%81%8D%E3%81%9F%E5%A0%B4%E5%90%88 + + それでも解決出来ない場合、コミュニティにてご報告ください。 + + +---------------------------------------------------------------- +■ コミュニティのご案内 +---------------------------------------------------------------- + + ニコニコミュニティ:https://com.nicovideo.jp/community/co5387214 + +  VMDサイジングやモーションサポーターなど、自作ツールに関する諸々実験室 +  一足早くβ版を試していただくことができます。 +  サイジングがうまくいかない場合のフォローなども行えたらいいなーと思ってます。 +  一応クローズドですが自動承認なのでお気軽にどうぞ + + +---------------------------------------------------------------- +■ 使用条件 他 +---------------------------------------------------------------- + + 《必須事項》 + +  ・設定した物理の結果を公開・配布する場合は、クレジットの明記のご協力をお願い致します +  ・ニコニコ動画の場合、コンテンツツリーへツリー用静画(im10854784)を登録してください +   ※コンテンツツリーに親登録していただける場合、クレジット記載は任意です +  ・モデルを不特定多数に配布される場合、配布告知元(動画等)にだけクレジット明記/コンテンツツリー登録をお願いいたします +   ※該当モデルを使用した作品にクレジット記載を求める必要はありません + + 《任意事項》 + +  本ツールおよび物理を設定したモデルに関して、元々のモデルの規約の範囲内で、以下の行為は自由に行って下さい + +  ・物理の調整・改変 +   ※配布モデルの場合、規約で物理の改変が許可されている事を確認してください +  ・動画投稿サイト、SNS等へのモデル使用動画投稿 +   ・進捗等で生成した物理設定が入ったモデルそのままを投稿することも問題ありません +   ・ただし、元々のモデルの規約で投稿先や年齢制限等の条件が規定されている場合、このツールで物理を設定したモデルもそれに準じます +  ・物理を設定したモデルの不特定多数への配布 +   ※自作モデルもしくは不特定多数への配布が許可されているモデルのみ + + 《禁止事項》 + +  本ツールおよび生成したモデルに関して、以下の行為はご遠慮願います + +  ・元々のモデル等の規約範囲外の行為 +  ・物理の完全自作発言 +  ・各権利者様のご迷惑になるような行為 +  ・他者の誹謗中傷目的の利用(二次元・三次元不問) + +  ・下記条件は禁止事項ではありませんが、ご配慮をお願いいたします +   『過度な暴力・猥褻・恋愛・猟奇的・政治的・宗教的表現を含む(R-15相当以上)作品への利用』 + +   ・必ず元々のモデル等の規約範囲をご確認の上、ご利用ください +   ・また作品を公開される際には、検索避け等のご配慮をよろしくお願いいたします + +  ※『営利目的の利用』は本ツールにおいては禁止事項ではありませんが、PMXEditorでは禁止事項に当たるためご注意ください + + 《免責事項》 + +  ・自己責任でご利用ください +  ・ツール使用によって生じたいかなる問題に関して、作者は一切の責任を負いかねます + + +---------------------------------------------------------------- +■ ソースコード・ライブラリ +---------------------------------------------------------------- + +このツールは、pythonで作成しており、以下ライブラリを使用・同梱しています。 + +・numpy (https://pypi.org/project/numpy/) +・bezier (https://pypi.org/project/bezier/) +・numpy-quaternion (https://pypi.org/project/numpy-quaternion/) +・wxPython (https://pypi.org/project/wxPython/) +・pyinstaller (https://pypi.org/project/PyInstaller/) + +ソースコードは、Githubで公開しています。(MITライセンス) +ただし、著作権は放棄しておりません。 + +https://github.com/miu200521358/pmx_tailor + +アイコンは、KindPng様よりお借りしています + + +---------------------------------------------------------------- +■ クレジット +---------------------------------------------------------------- + + ツール名: PmxTailor もしくは Pmxテイラー + 作者: miu もしくは miu200521358 + + http://www.nicovideo.jp/user/2776342 + Twitter: @miu200521358 + Mail: garnet200521358@gmail.com + + +---------------------------------------------------------------- +■ 履歴 +---------------------------------------------------------------- + +ver2.01.00(2023/02/18) +■機能追加・修正 + ・メッシュ走査・ボーンマッピングロジック変更 + ・物理パラ調整 +  ・プリセットも調整 +  ・プリセット「ウール」を追加 + ・不定形なメッシュ用に特殊形状「面欠け」追加 + ・ジョイントの位置を「ボーン位置」に置くように変更 +  ・パラ調整(詳細)画面の詳細オプションから従来の「ボーン間」に変更可 + ・モデルコメントに指定したパラ全ての情報を出力するよう追加 + ・ジョイントの横移動制限をボーンの距離に合わせた量に計算するよう修正 +■不具合修正 + ・下部エッジを検出する際の閾値が全体の中央値になっていたので、上部エッジの中央値に修正 + ・縦ジョイントがなかった場合のログを、根元とそれ以降でメッセージを分けるよう修正 + ・剛体の向きがおかしくなる場合があるのを修正 + ・ウェイト二度塗りを避けるよう、ウェイト塗りの順番を修正 + ・再利用で一列だけで布プリセットを使用した場合、横を強制的に参照しようとしてエラーになっていたのを修正 + +ver2.00.03(2022/11/19) +■機能追加 + ・選択されたメッシュの真ん中にのみボーンを張る「密度基準:中央」を追加 + ・裾対象頂点CSV欄追加 +■不具合修正 + ・剛体とジョイントの仮想頂点取得時のチェック追加 + ・末端の仮想ボーンを常にメッシュ一行分の幅で生成するよう変更 + ・頂点マップ検算時、横の繋がりよりも根元を繋げることを優先するよう変更 + ・「密度基準:中央」時のボーンの生成箇所を「奇数 = 真ん中、偶数 = 始点寄り」に変更 + ・一枚物メッシュの根元頂点CSV必須チェックを除外 + ・縦ジョイント生成に失敗した場合の対処方法追加 + +ver2.00.02(2022/09/13) +■機能変更 + ・PmxEditor0.2.7.3でCSV出力機能のフォーマットがUTF-8になったため、UTF-8でのパースも試行リストに追加 +  ※フォーマットは既存同様のもの(汎用用途)のみ想定しています +■不具合修正 + ・SDEF+再利用オプション時にボーンマップ生成に失敗していたのを修正 + ・再利用選択時の既存物理削除処理を一旦スルー + ・ジョイント生成時のパラマッピング時INDEX割り当て処理変更 + +ver2.00.01(2022/07/18) +■不具合修正 + ・ジョイントの最小移動制限に不要な値が入っていたため削除 + +ver2.00.00 (2022/07/18) + ・メッシュ走査方法再構築 + ・Vroid2Pmx設定インポート機能追加 + ・一枚物の場合には根元頂点CSVを必須とするよう判定追加 + ・親ボーンと物理開始地点をウェイトグラデ設定する「物理グラデーション対象頂点CSV」追加 +  ・指定された範囲を親ボーンと物理設定対象ボーンの中から近いボーン4つでウェイト生成 + ・剛体の厚みオプション追加 +  ・デフォルト:根元 0.07、末端 0.2 + ・剛体とジョイントの配置を変更 +  ・ボーン間:よくある剛体を繋ぐ位置にジョイントを配置するパターン。柔らかいスカート等に向いてる。 +  ・ボーン位置:剛体ではなく関節であるボーン位置にジョイントを配置する。逆ジョイントを入れてマントとかに向いてる。 + ・頂点ルート探索方法オプション追加 +  ・根元頂点優先:(デフォルト)末端から根元への向きを優先(前頂点との内積差は考慮しない) +  ・前頂点優先:前頂点との内積差を加味して、「まっすぐ」を選ぶ + ・根元推定頂点の計算方法オプション追加 +  ・角度:末端頂点角度に類似した根元頂点を推定 +  ・縮尺: 末端頂点円周と根元頂点円周の縮尺を推定 + ・胸物理をN式ベースに変更 + + +ver1.00.02 (2021/12/26) + ・略称設定ENTER押下時に過去設定を再設定するよう機能追加 + ・(略称)中心ボーンで該当物理を動かせるよう剛体接続調整 + ・密度基準フラグ追加(頂点ベースの場合、一頂点一剛体で生成可能) + ・材質を再選択したときに「パラ調整(ボーン)」タブ内のグリッドがまれに描画がおかしくなる不具合を修正 + ・エラーハンドリング追加 + ・初期面取得処理調整 + +ver1.00.01 (2021/12/04) + ・胸プリセット追加 + ・画面縦幅を少しだけ拡張(パラ調整タブでスクロールを一番下に持ってきた時に材質名から表示されるように) + ・パラ調整の質量パラメーターの最大値を5 → 10に変更(既存プリセットの挙動は変わらず) + ・既に同一名の剛体が存在していた場合に挙動がおかしくなっていた為、追加剛体に末尾3桁乱数を追加するよう変更 + ・モデルコメントの材質パラメーターを一行にまとめるよう変更 + ・「パラ調整(詳細)」「パラ調整(ボーン)」タブの材質名に材質略称を追記 + +ver1.00.00 (2021/12/01) +  ・一般配布開始 + + + diff --git "a/\351\205\215\345\270\203/v2.1.0/VMD\343\202\265\343\202\244\343\202\270\343\203\263\343\202\260Wiki.url" "b/\351\205\215\345\270\203/v2.1.0/VMD\343\202\265\343\202\244\343\202\270\343\203\263\343\202\260Wiki.url" new file mode 100644 index 0000000..ea64cf4 --- /dev/null +++ "b/\351\205\215\345\270\203/v2.1.0/VMD\343\202\265\343\202\244\343\202\270\343\203\263\343\202\260Wiki.url" @@ -0,0 +1,2 @@ +[InternetShortcut] + URL=https://github.com/miu200521358/vmd_sizing/wiki \ No newline at end of file diff --git "a/\351\205\215\345\270\203/v2.1.0/\343\203\213\343\202\263\343\203\213\343\202\263\343\203\237\343\203\245\343\203\213\343\203\206\343\202\243.url" "b/\351\205\215\345\270\203/v2.1.0/\343\203\213\343\202\263\343\203\213\343\202\263\343\203\237\343\203\245\343\203\213\343\203\206\343\202\243.url" new file mode 100644 index 0000000..454f930 --- /dev/null +++ "b/\351\205\215\345\270\203/v2.1.0/\343\203\213\343\202\263\343\203\213\343\202\263\343\203\237\343\203\245\343\203\213\343\203\206\343\202\243.url" @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://com.nicovideo.jp/community/co5387214