void EndOfScript(MMD.PMD.PMDFormat format) { AssetDatabase.Refresh(); this.mesh = null; this.materials = null; this.bones = null; this.pmd = null; }
// Use this for initialization public PMDLoaderScript(Object pmdFile, MMD.PMD.ShaderType shader_type, bool rigidFlag) { this.pmd = pmdFile; this.rigidFlag = rigidFlag; this.shader_type = shader_type; if (this.pmd != null) { LoadPMDFile(); } }
void CreatePrefab(MMD.PMD.PMDFormat format) { Object prefab = PrefabUtility.CreateEmptyPrefab(format.folder + "/" + format.name + ".prefab"); #if UNITY_4_0 || UNITY_3_5 // 4.0からPrefabUtilityを使えとのこと // 3.5.6f4でもコンソールで警告がでていたので3.5もこっち PrefabUtility.ReplacePrefab(format.caller, prefab); #elif UNITY_3_4 EditorUtility.ReplacePrefab(format.caller, prefab); #endif }
// Use this for initialization public PMDLoaderScript (Object pmdFile, MMD.PMD.ShaderType shader_type, bool rigidFlag, bool use_mecanim, bool use_ik) { this.pmd = pmdFile; this.rigidFlag = rigidFlag; this.shader_type = shader_type; this.use_mecanim = use_mecanim; this.use_ik = use_ik; if (this.pmd != null) { LoadPMDFile(); } }
// PMDファイルをUnity形式に変換 void BurnUnityFormatForPMD(MMD.PMD.PMDFormat format) { format.fst = this.fst; obj = new GameObject(format.name); format.caller = obj; format.shader_type = this.shader_type; MMD.PMD.PMDConverter conv = new MMD.PMD.PMDConverter(); this.mesh = conv.CreateMesh(format); // メッシュの生成・設定 this.materials = conv.CreateMaterials(format); // マテリアルの生成・設定 this.bones = conv.CreateBones(format); // ボーンの生成・設定 // バインドポーズの作成 conv.BuildingBindpose(format, this.mesh, this.materials, this.bones); obj.AddComponent<Animation>(); // アニメーションを追加 MMDEngine engine = obj.AddComponent<MMDEngine>(); // IKの登録 if(this.use_ik) engine.ik_list = conv.EntryIKSolver(format, this.bones); // 剛体関連 if (this.rigidFlag) { try { this.rigids = conv.CreateRigids(format, bones); conv.AssignRigidbodyToBone(format, this.bones, this.rigids); conv.SetRigidsSettings(format, this.bones, this.rigids); conv.SettingJointComponent(format, this.bones, this.rigids); // 非衝突グループ List<int>[] ignoreGroups = conv.SettingIgnoreRigidGroups(format, this.rigids); int[] groupTarget = conv.GetRigidbodyGroupTargets(format, rigids); MMDEngine.Initialize(engine, groupTarget, ignoreGroups, this.rigids); } catch { } } #if UNITY_4_0 AvatarSettingScript avt_setting = new AvatarSettingScript(format.caller); avt_setting.SettingAvatar(); #endif var window = LoadedWindow.Init(); window.Text = format.head.comment; CreatePrefab(format); EndOfScript(format); }
public string MMDListToPrint() { string str = "["; if (this.listMultimedia != null) { foreach (MultimediaDevice MMD in this.listMultimedia) { str += "{" + MMD.ToString() + "},"; } str = str.Remove(str.Length - 1); } return(str + "]"); }
void CreatePrefab(MMD.PMD.PMDFormat format) { Object prefab = PrefabUtility.CreateEmptyPrefab(format.folder + "/" + format.name + ".prefab"); EditorUtility.ReplacePrefab(format.caller, prefab); }
void BurnUnityFormatForVMD(MMD.VMD.VMDFormat format) { MMD.VMD.VMDConverter conv = new MMD.VMD.VMDConverter(); conv.CreateAnimationClip(format, this.assign_pmd, this.anim, this.create_asset, this.interpolationQuality); }
// 移動のみの抽出 void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path) { try { List<MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone]; List<Keyframe> lx_keys = new List<Keyframe>(); List<Keyframe> ly_keys = new List<Keyframe>(); List<Keyframe> lz_keys = new List<Keyframe>(); for (int i = 0; i < mlist.Count; i++) { const float tick_time = 1.0f / 30.0f; // 0だけのいらんデータを捨てる if (Vector3.zero != mlist[i].location) { float tick = mlist[i].flame_no * tick_time; float a_x, a_y, a_z, b_x, b_y, b_z; // 各軸別々に補間が付いてる a_x = GetTangent(mlist[i].interpolation, 0, 0); a_y = GetTangent(mlist[i].interpolation, 1, 0); a_z = GetTangent(mlist[i].interpolation, 2, 0); b_x = GetTangent(mlist[i].interpolation, 0, 1); b_y = GetTangent(mlist[i].interpolation, 1, 1); b_z = GetTangent(mlist[i].interpolation, 2, 1); lx_keys.Add(new Keyframe(tick, mlist[i].location.x, a_x, b_x)); ly_keys.Add(new Keyframe(tick, mlist[i].location.y, a_y, b_y)); lz_keys.Add(new Keyframe(tick, mlist[i].location.z, a_z, b_z)); } } // 回転ボーンの場合はデータが入ってないはず int count = lx_keys.Count; if (count != 0) { AnimationCurve curve_x = new AnimationCurve(lx_keys.ToArray()); AnimationCurve curve_y = new AnimationCurve(ly_keys.ToArray()); AnimationCurve curve_z = new AnimationCurve(lz_keys.ToArray()); clip.SetCurve(bone_path, typeof(Transform), "localPosition.x", curve_x); clip.SetCurve(bone_path, typeof(Transform), "localPosition.y", curve_y); clip.SetCurve(bone_path, typeof(Transform), "localPosition.z", curve_z); } } catch (KeyNotFoundException) { //Debug.LogError("互換性のないボーンが読み込まれました:" + current_bone); } }
// あるボーンに含まれるキーフレを抽出 // これは回転のみ void CreateKeysForRotation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path) { try { List<MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone]; Keyframe[] rx_keys = new Keyframe[mlist.Count]; Keyframe[] ry_keys = new Keyframe[mlist.Count]; Keyframe[] rz_keys = new Keyframe[mlist.Count]; Keyframe[] rw_keys = new Keyframe[mlist.Count]; for (int i = 0; i < mlist.Count; i++) { const float tick_time = 1.0f / 30.0f; float tick = mlist[i].flame_no * tick_time; float a = GetTangent(mlist[i].interpolation, 3, 0); // inTangent float b; // outTangent // -1フレにはoutTangentは存在しないのでcatch try { b = GetTangent(mlist[i-1].interpolation, 3, 1); } catch { b = 0; } rx_keys[i] = new Keyframe(tick, mlist[i].rotation.x, a, b); ry_keys[i] = new Keyframe(tick, mlist[i].rotation.y, a, b); rz_keys[i] = new Keyframe(tick, mlist[i].rotation.z, a, b); rw_keys[i] = new Keyframe(tick, mlist[i].rotation.w, a, b); } AnimationCurve curve_x = new AnimationCurve(rx_keys); AnimationCurve curve_y = new AnimationCurve(ry_keys); AnimationCurve curve_z = new AnimationCurve(rz_keys); AnimationCurve curve_w = new AnimationCurve(rw_keys); // ここで回転クォータニオンをセット clip.SetCurve(bone_path, typeof(Transform), "localRotation.x", curve_x); clip.SetCurve(bone_path, typeof(Transform), "localRotation.y", curve_y); clip.SetCurve(bone_path, typeof(Transform), "localRotation.z", curve_z); clip.SetCurve(bone_path, typeof(Transform), "localRotation.w", curve_w); } catch (KeyNotFoundException) { //Debug.LogError("互換性のないボーンが読み込まれました:" + bone_path); } }
// クリップをアニメーションに登録する public void CreateAnimationClip(MMD.VMD.VMDFormat format, GameObject assign_pmd, Animation anim) { //Animation anim = assign_pmd.GetComponent<Animation>(); // クリップの作成 AnimationClip clip = new AnimationClip(); clip.name = format.clip_name; Dictionary<string, string> bone_path = new Dictionary<string, string>(); Dictionary<string, GameObject> gameobj = new Dictionary<string, GameObject>(); GetGameObjects(gameobj, assign_pmd); // 親ボーン下のGameObjectを取得 FullSearchBonePath(assign_pmd.transform, bone_path); FullEntryBoneAnimation(format, clip, bone_path, gameobj); CreateKeysForSkin(format, clip); // 表情の追加 // ここで登録 //anim.AddClip(clip, format.clip_name); Debug.Log(AssetDatabase.GetAssetPath(assign_pmd)); AssetDatabase.AddObjectToAsset(clip, AssetDatabase.GetAssetPath(assign_pmd)); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(clip)); }
// 無駄なカーブを登録してるけどどうするか void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary<string, string> dic, Dictionary<string, GameObject> obj) { foreach (KeyValuePair<string, string> p in dic) // keyはtransformの名前, valueはパス { bool entry_flag = true; foreach (var g in obj) // 互いに名前の一致する場合にRigidbodyが存在するか調べたい { if (p.Key == g.Key) { var rigid = g.Value.GetComponent<Rigidbody>(); if (rigid != null && !rigid.isKinematic) { // rigidbodyの取得ができてしまったので無視させる entry_flag = false; //Debug.Log(rigid.name); } } } if (!entry_flag) continue; // Rigidbodyがある場合はキーフレの登録を無視する CreateKeysForLocation(format, clip, p.Key, p.Value); CreateKeysForRotation(format, clip, p.Key, p.Value); } }
void CreateKeysForSkin(MMD.VMD.VMDFormat format, AnimationClip clip) { const float tick_time = 1f / 30f; // 全ての表情に打たれているキーフレームを探索 List<VMD.VMDFormat.SkinData> s; foreach (var skin in format.skin_list.skin) { s = skin.Value; Keyframe[] keyframe = new Keyframe[skin.Value.Count]; // キーフレームの登録を行う for (int i = 0; i < skin.Value.Count; i++) keyframe[i] = new Keyframe(s[i].flame_no * tick_time, s[i].weight); // Z軸移動にキーフレームを打つ AnimationCurve curve = new AnimationCurve(keyframe); clip.SetCurve(format.pmd + "/Expression/" + skin.Key, typeof(Transform), "localPosition.z", curve); } }
// クリップをアニメーションに登録する public void CreateAnimationClip(MMD.VMD.VMDFormat format, GameObject assign_pmd, Animation anim, bool create_asset) { //Animation anim = assign_pmd.GetComponent<Animation>(); // クリップの作成 AnimationClip clip = new AnimationClip(); clip.name = format.clip_name; Dictionary<string, string> bone_path = new Dictionary<string, string>(); Dictionary<string, GameObject> gameobj = new Dictionary<string, GameObject>(); GetGameObjects(gameobj, assign_pmd); // 親ボーン下のGameObjectを取得 FullSearchBonePath(assign_pmd.transform, bone_path); FullEntryBoneAnimation(format, clip, bone_path, gameobj); CreateKeysForSkin(format, clip); // 表情の追加 // ここで登録 //anim.AddClip(clip, format.clip_name); if (create_asset) { // フォルダを生成してアニメーションのファイルを書き出す string prefab_folder = AssetDatabase.GetAssetPath(assign_pmd); prefab_folder = Path.GetDirectoryName(prefab_folder); Debug.Log(prefab_folder); if (!Directory.Exists(prefab_folder + "/Animation")) AssetDatabase.CreateFolder(prefab_folder, "Animation"); AssetDatabase.CreateAsset(clip, prefab_folder + "/Animation/" + clip.name + ".anim"); } else { // こちらはPrefabの中に入れるタイプ AssetDatabase.AddObjectToAsset(clip, AssetDatabase.GetAssetPath(assign_pmd)); } AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(clip)); }
// 無駄なカーブを登録してるけどどうするか void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary<string, string> dic, Dictionary<string, GameObject> obj) { foreach (KeyValuePair<string, string> p in dic) // keyはtransformの名前, valueはパス { // 互いに名前の一致する場合にRigidbodyが存在するか調べたい GameObject current_obj = null; if(obj.ContainsKey(p.Key)){ current_obj = obj[p.Key]; // Rigidbodyがある場合はキーフレの登録を無視する var rigid = current_obj.GetComponent<Rigidbody>(); if (rigid != null && !rigid.isKinematic) { continue; } } // キーフレの登録 CreateKeysForLocation(format, clip, p.Key, p.Value, current_obj); CreateKeysForRotation(format, clip, p.Key, p.Value); } }
void BurnUnityFormatForVMD(MMD.VMD.VMDFormat format) { MMD.VMD.VMDConverter conv = new MMD.VMD.VMDConverter(); conv.CreateAnimationClip(format, this.assign_pmd, this.anim); }