/// <summary> /// 初回処理 /// </summary> public void Awake() { MorphManager self = (MorphManager)target; children_ = new Transform[System.Enum.GetValues(typeof(MorphManager.PanelType)).Length][]; //子登録 for (int i = 0, i_max = children_.Length; i < i_max; ++i) { children_[i] = self.vertex_morph.script.Where(x => x.panel == (MorphManager.PanelType)i) .Select(x => x.transform) .Concat(self.uv_morph.SelectMany(x => x.script) .Where(x => x.panel == (MorphManager.PanelType)i) .Select(x => x.transform) ) .Concat(self.material_morph.script.Where(x => x.panel == (MorphManager.PanelType)i) .Select(x => x.transform) ) .Concat(self.bone_morph.script.Where(x => x.panel == (MorphManager.PanelType)i) .Select(x => x.transform) ) .Concat(self.group_morph.script.Where(x => x.panel == (MorphManager.PanelType)i) .Select(x => x.transform) ) .ToArray(); } }
/// <summary> /// 材質モーフ作成 /// </summary> /// <param name='morph_manager'>表情マネージャー</param> /// <param name='morphs'>モーフのゲームオブジェクト</param> /// <param name='creation_info'>メッシュ作成情報</param> void CreateMaterialMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) { //インデックスと元データの作成 List<uint> original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Material == x.morph_type)) //該当モーフに絞る .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.MaterialMorphOffset)y).material_index)) //インデックスの取り出しと連結 .Distinct() //重複したインデックスの削除 .ToList(); //ソートに向けて一旦リスト化 original_indices.Sort(); //ソート if (uint.MaxValue == original_indices.LastOrDefault()) { //最後が uint.MaxValue(≒-1) なら //全材質対象が存在するので全インデックスを取得 original_indices = Enumerable.Range(0, format_.material_list.material.Length + 1).Select(x=>(uint)x).ToList(); original_indices[format_.material_list.material.Length] = uint.MaxValue; //uint.MaxValueを忘れない } int[] indices = original_indices.Select(x=>(int)x).ToArray(); MaterialMorph.MaterialMorphParameter[] source = indices.Where(x=>x<format_.material_list.material.Length) .Select(x=>{ //インデックスを用いて、元データをパック MaterialMorph.MaterialMorphParameter result = new MaterialMorph.MaterialMorphParameter(); if (0 <= x) { //-1(全材質対象)で無いなら //元データを取得 PMXFormat.Material y = format_.material_list.material[x]; result.color = y.diffuse_color; result.specular = new Color(y.specular_color.r, y.specular_color.g, y.specular_color.b, y.specularity); result.ambient = y.ambient_color; result.outline_color = y.edge_color; result.outline_width = y.edge_size; result.texture_color = Color.white; result.sphere_color = Color.white; result.toon_color = Color.white; } else { //-1(全材質対象)なら //適当にでっち上げる result = MaterialMorph.MaterialMorphParameter.zero; } return result; }) .ToArray(); //インデックス逆引き用辞書の作成 Dictionary<uint, uint> index_reverse_dictionary = new Dictionary<uint, uint>(); for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { index_reverse_dictionary.Add((uint)indices[i], i); } //個別モーフスクリプトの作成 MaterialMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) .Where(x=>PMXFormat.MorphData.MorphType.Material == format_.morph_list.morph_data[x].morph_type) //該当モーフに絞る .Select(x=>AssignMaterialMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) .ToArray(); //材質リアサイン辞書の作成 Dictionary<uint, uint>[] material_reassign_dictionary = new Dictionary<uint, uint>[creation_info.Length + 1]; for (int i = 0, i_max = creation_info.Length; i < i_max; +++i) { material_reassign_dictionary[i] = new Dictionary<uint, uint>(); for (uint k = 0, k_max = (uint)creation_info[i].value.Length; k < k_max; ++k) { material_reassign_dictionary[i][creation_info[i].value[k].material_index] = k; } if (-1 == indices.LastOrDefault()) { //indices の最後が -1(≒uint.MaxValue) なら //全材質対象が存在するので材質リアサイン辞書に追加 material_reassign_dictionary[i][uint.MaxValue] = uint.MaxValue; } } //メッシュ別インデックスの作成 int invalid_material_index = format_.material_list.material.Length; MorphManager.MaterialMorphPack.Meshes[] multi_indices = new MorphManager.MaterialMorphPack.Meshes[creation_info.Length]; for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { multi_indices[i] = new MorphManager.MaterialMorphPack.Meshes(); multi_indices[i].indices = new int[indices.Length]; for (int k = 0, k_max = indices.Length; k < k_max; ++k) { if (material_reassign_dictionary[i].ContainsKey((uint)indices[k])) { //この材質で有効なら multi_indices[i].indices[k] = (int)material_reassign_dictionary[i][(uint)indices[k]]; } else { //この材質では無効なら multi_indices[i].indices[k] = invalid_material_index; //最大材質数を設定(uint.MaxValueでは無いので注意) } } } //表情マネージャーにインデックス・元データ・スクリプトの設定 morph_manager.material_morph = new MorphManager.MaterialMorphPack(multi_indices, source, script); }
/// <summary> /// グループモーフ作成 /// </summary> /// <param name='morph_manager'>表情マネージャー</param> /// <param name='morphs'>モーフのゲームオブジェクト</param> void CreateGroupMorph(MorphManager morph_manager, GameObject[] morphs) { //インデックスと元データの作成 List<uint> original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Group == x.morph_type)) //該当モーフに絞る .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.GroupMorphOffset)y).morph_index)) //インデックスの取り出しと連結 .Distinct() //重複したインデックスの削除 .ToList(); //ソートに向けて一旦リスト化 original_indices.Sort(); //ソート int[] indices = original_indices.Select(x=>(int)x).ToArray(); float[] source = Enumerable.Repeat(0.0f, indices.Length) //インデックスを用いて、元データをパック .ToArray(); //インデックス逆引き用辞書の作成 Dictionary<uint, uint> index_reverse_dictionary = new Dictionary<uint, uint>(); for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { index_reverse_dictionary.Add((uint)indices[i], i); } //個別モーフスクリプトの作成 GroupMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) .Where(x=>PMXFormat.MorphData.MorphType.Group == format_.morph_list.morph_data[x].morph_type) //該当モーフに絞る .Select(x=>AssignGroupMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) .ToArray(); //表情マネージャーにインデックス・元データ・スクリプトの設定 morph_manager.group_morph = new MorphManager.GroupMorphPack(indices, source, script); }
/// <summary> /// ボーンモーフ作成 /// </summary> /// <param name='morph_manager'>表情マネージャー</param> /// <param name='morphs'>モーフのゲームオブジェクト</param> void CreateBoneMorph(MorphManager morph_manager, GameObject[] morphs) { //インデックスと元データの作成 List<uint> original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Bone == x.morph_type)) //該当モーフに絞る .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.BoneMorphOffset)y).bone_index)) //インデックスの取り出しと連結 .Distinct() //重複したインデックスの削除 .ToList(); //ソートに向けて一旦リスト化 original_indices.Sort(); //ソート int[] indices = original_indices.Select(x=>(int)x).ToArray(); BoneMorph.BoneMorphParameter[] source = indices.Where(x=>x<format_.bone_list.bone.Length) .Select(x=>{ //インデックスを用いて、元データをパック PMXFormat.Bone y = format_.bone_list.bone[x]; BoneMorph.BoneMorphParameter result = new BoneMorph.BoneMorphParameter(); result.position = y.bone_position; if (y.parent_bone_index < (uint)format_.bone_list.bone.Length) { //親が居たらローカル座標化 result.position -= format_.bone_list.bone[y.parent_bone_index].bone_position; } result.position *= scale_; result.rotation = Quaternion.identity; return result; }) .ToArray(); //インデックス逆引き用辞書の作成 Dictionary<uint, uint> index_reverse_dictionary = new Dictionary<uint, uint>(); for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { index_reverse_dictionary.Add((uint)indices[i], i); } //個別モーフスクリプトの作成 BoneMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) .Where(x=>PMXFormat.MorphData.MorphType.Bone == format_.morph_list.morph_data[x].morph_type) //該当モーフに絞る .Select(x=>AssignBoneMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) .ToArray(); //表情マネージャーにインデックス・元データ・スクリプトの設定 morph_manager.bone_morph = new MorphManager.BoneMorphPack(indices, source, script); }
/// <summary> /// 頂点モーフ作成 /// </summary> /// <param name='morph_manager'>表情マネージャー</param> /// <param name='morphs'>モーフのゲームオブジェクト</param> /// <param name='creation_info'>メッシュ作成情報</param> void CreateVertexMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) { //インデックスと元データの作成 List<uint> original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Vertex == x.morph_type)) //該当モーフに絞る .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.VertexMorphOffset)y).vertex_index)) //インデックスの取り出しと連結 .Distinct() //重複したインデックスの削除 .ToList(); //ソートに向けて一旦リスト化 original_indices.Sort(); //ソート int[] indices = original_indices.Select(x=>(int)x).ToArray(); Vector3[] source = indices.Select(x=>format_.vertex_list.vertex[x].pos * scale_) //インデックスを用いて、元データをパック .ToArray(); //インデックス逆引き用辞書の作成 Dictionary<uint, uint> index_reverse_dictionary = new Dictionary<uint, uint>(); for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { index_reverse_dictionary.Add((uint)indices[i], i); } //個別モーフスクリプトの作成 VertexMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) .Where(x=>PMXFormat.MorphData.MorphType.Vertex == format_.morph_list.morph_data[x].morph_type) //該当モーフに絞る .Select(x=>AssignVertexMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) .ToArray(); //メッシュ別インデックスの作成 int invalid_vertex_index = format_.vertex_list.vertex.Length; MorphManager.VertexMorphPack.Meshes[] multi_indices = new MorphManager.VertexMorphPack.Meshes[creation_info.Length]; for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { multi_indices[i] = new MorphManager.VertexMorphPack.Meshes(); multi_indices[i].indices = new int[indices.Length]; for (int k = 0, k_max = indices.Length; k < k_max; ++k) { if (creation_info[i].reassign_dictionary.ContainsKey((uint)indices[k])) { //このメッシュで有効なら multi_indices[i].indices[k] = (int)creation_info[i].reassign_dictionary[(uint)indices[k]]; } else { //このメッシュでは無効なら multi_indices[i].indices[k] = invalid_vertex_index; //最大頂点数を設定(uint.MaxValueでは無いので注意) } } } //表情マネージャーにインデックス・元データ・スクリプトの設定 morph_manager.vertex_morph = new MorphManager.VertexMorphPack(multi_indices, source, script); }
/// <summary> /// UV・追加UVモーフ作成 /// </summary> /// <param name='morph_manager'>表情マネージャー</param> /// <param name='morphs'>モーフのゲームオブジェクト</param> /// <param name='creation_info'>メッシュ作成情報</param> void CreateUvMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) { for (int morph_type_index = 0, morph_type_index_max = 1 + format_.header.additionalUV; morph_type_index < morph_type_index_max; ++morph_type_index) { //モーフタイプ PMXFormat.MorphData.MorphType morph_type; switch (morph_type_index) { case 0: morph_type = PMXFormat.MorphData.MorphType.Uv; break; case 1: morph_type = PMXFormat.MorphData.MorphType.Adduv1; break; case 2: morph_type = PMXFormat.MorphData.MorphType.Adduv2; break; case 3: morph_type = PMXFormat.MorphData.MorphType.Adduv3; break; case 4: morph_type = PMXFormat.MorphData.MorphType.Adduv4; break; default: throw new System.ArgumentOutOfRangeException(); } //インデックスと元データの作成 List<uint> original_indices = format_.morph_list.morph_data.Where(x=>(morph_type == x.morph_type)) //該当モーフに絞る .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.UVMorphOffset)y).vertex_index)) //インデックスの取り出しと連結 .Distinct() //重複したインデックスの削除 .ToList(); //ソートに向けて一旦リスト化 original_indices.Sort(); //ソート int[] indices = original_indices.Select(x=>(int)x).ToArray(); Vector2[] source; if (0 == morph_type_index) { //通常UV source = indices.Select(x=>format_.vertex_list.vertex[x].uv) //インデックスを用いて、元データをパック .Select(x=>new Vector2(x.x, x.y)) .ToArray(); } else { //追加UV source = indices.Select(x=>format_.vertex_list.vertex[x].add_uv[morph_type_index - 1]) //インデックスを用いて、元データをパック .Select(x=>new Vector2(x.x, x.y)) .ToArray(); } //インデックス逆引き用辞書の作成 Dictionary<uint, uint> index_reverse_dictionary = new Dictionary<uint, uint>(); for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { index_reverse_dictionary.Add((uint)indices[i], i); } //個別モーフスクリプトの作成 UvMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) .Where(x=>morph_type == format_.morph_list.morph_data[x].morph_type) //該当モーフに絞る .Select(x=>AssignUvMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) .ToArray(); //メッシュ別インデックスの作成 int invalid_vertex_index = format_.vertex_list.vertex.Length; MorphManager.UvMorphPack.Meshes[] multi_indices = new MorphManager.UvMorphPack.Meshes[creation_info.Length]; for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { multi_indices[i] = new MorphManager.UvMorphPack.Meshes(); multi_indices[i].indices = new int[indices.Length]; for (int k = 0, k_max = indices.Length; k < k_max; ++k) { if (creation_info[i].reassign_dictionary.ContainsKey((uint)indices[k])) { //このメッシュで有効なら multi_indices[i].indices[k] = (int)creation_info[i].reassign_dictionary[(uint)indices[k]]; } else { //このメッシュでは無効なら multi_indices[i].indices[k] = invalid_vertex_index; //最大頂点数を設定(uint.MaxValueでは無いので注意) } } } //表情マネージャーにインデックス・元データ・スクリプトの設定 morph_manager.uv_morph[morph_type_index] = new MorphManager.UvMorphPack(multi_indices, source, script); } }