public HelixViewerPanel(string path)
        {
            InitializeComponent();

            var builder = new MeshBuilder();

            format_ = LoadPmxMaterials(path);
            MeshCreationInfo creation_info = CreateMeshCreationInfoSingle();


            var mats = format_.material_list.material.Length;

            var models = new Model3DGroup();

            for (int i = 0, i_max = creation_info.value.Length; i < i_max; ++i)
            {
                //format_.face_vertex_list.face_vert_indexを[start](含む)から[start+count](含まず)迄取り出し
                int[] indices = creation_info.value[i].plane_indices.Select(x => (int)creation_info.reassign_dictionary[x]) //頂点リアサインインデックス変換
                                .ToArray();
                MeshGeometry3D mesh = new MeshGeometry3D();

                mesh.Positions = new Point3DCollection(format_.vertex_list.vertex.Select(x => x.pos));

                mesh.TextureCoordinates = new PointCollection(format_.vertex_list.vertex.Select(x => x.uv));

                indices.ToList()
                .ForEach(x => mesh.TriangleIndices.Add(x));

                var textureIndex = format_.material_list.material[i].usually_texture_index;

                Material material;

                if (textureIndex == uint.MaxValue)
                {
                    material = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(160, 160, 160)));
                }
                else
                {
                    //  Texture
                    ImageBrush colors_brush = new ImageBrush
                    {
                        ImageSource = new BitmapImage(
                            new Uri(Path.Combine(format_.meta_header.folder,
                                                 format_.texture_list.texture_file[textureIndex]), UriKind.Relative))
                    };
                    material =
                        new DiffuseMaterial(colors_brush);
                }

                var model = new GeometryModel3D(mesh, material);
                model.BackMaterial = material;
                models.Children.Add(model);
            }
            PreviewModel.Content = models;
        }
Пример #2
0
        /// <summary>
        ///     メッシュを作成する為の情報を作成(複数メッシュ版)
        /// </summary>
        /// <returns>メッシュ作成情報</returns>
        private MeshCreationInfo[] CreateMeshCreationInfoMulti()
        {
            //マテリアル単位のMeshCreationInfo.Packを作成する
            var packs = CreateMeshCreationInfoPacks();

            //マテリアル細分化
            packs = SplitSubMesh(packs);
            //頂点数の多い順に並べる(メッシュ分割アルゴリズム上、後半に行く程頂点数が少ない方が敷き詰め効率が良い)
            Array.Sort(packs, (x, y) => y.vertices.Length - x.vertices.Length);

            var result = new List <MeshCreationInfo>();

            do
            {
                uint vertex_sum = 0;
                var  info       = new MeshCreationInfo();
                //マテリアルパック作成
                info.value = Enumerable.Range(0, packs.Length)
                             .Where(x => null != packs[x]) //有効なマテリアルに絞る
                             .Where(x =>
                {
                    //採用しても頂点数が限界を超えないなら
                    vertex_sum += (uint)packs[x].vertices.Length;
                    return(vertex_sum < c_max_vertex_count_in_mesh);
                })
                             .Select(x =>
                {
                    //マテリアルの採用と無効化
                    var pack = packs[x];
                    packs[x] = null;
                    return(pack);
                })
                             .ToArray();
                //マテリアルインデックスに並べる(メッシュの選定が終わったので見易い様に並びを戻す)
                Array.Sort(info.value,
                           (x, y) => x.material_index > y.material_index ? 1 : x.material_index < y.material_index ? -1 : 0);
                //総頂点作成
                info.all_vertices = info.value.SelectMany(x => x.vertices).Distinct().ToArray();
                Array.Sort(info.all_vertices);
                //頂点リアサインインデックス用辞書作成
                info.reassign_dictionary = new Dictionary <uint, uint>();
                uint reassign_index = 0;
                foreach (var i in info.all_vertices)
                {
                    info.reassign_dictionary[i] = reassign_index++;
                }
                //戻り値に追加
                result.Add(info);
            } while (packs.Any(x => null != x)); //使用していないマテリアルが為るならループ

            return(result.ToArray());
        }
Пример #3
0
 /// <summary>
 ///     メッシュにサブメッシュを登録する
 /// </summary>
 /// <param name='mesh'>対象メッシュ</param>
 /// <param name='creation_info'>メッシュ作成情報</param>
 private void SetSubMesh(Mesh mesh, MeshCreationInfo creation_info)
 {
     // マテリアル対サブメッシュ
     // サブメッシュとはマテリアルに適用したい面頂点データのこと
     // 面ごとに設定するマテリアルはここ
     mesh.subMeshCount = creation_info.value.Length;
     for (int i = 0, i_max = creation_info.value.Length; i < i_max; ++i)
     {
         //format_.face_vertex_list.face_vert_indexを[start](含む)から[start+count](含まず)迄取り出し
         var indices = creation_info.value[i].plane_indices
                       .Select(x => (int)creation_info.reassign_dictionary[x]) //頂点リアサインインデックス変換
                       .ToArray();
         mesh.SetTriangles(indices, i);
     }
 }
        MeshCreationInfo CreateMeshCreationInfoSingle()
        {
            MeshCreationInfo result = new MeshCreationInfo();

            //全マテリアルを設定
            result.value = CreateMeshCreationInfoPacks();
            //全頂点を設定
            result.all_vertices = Enumerable.Range(0, format_.vertex_list.vertex.Length).Select(x => (uint)x).ToArray();
            //頂点リアサインインデックス用辞書作成
            result.reassign_dictionary = new Dictionary <uint, uint>(result.all_vertices.Length);
            for (uint i = 0, i_max = (uint)result.all_vertices.Length; i < i_max; ++i)
            {
                result.reassign_dictionary[i] = i;
            }
            return(result);
        }
Пример #5
0
 /// <summary>
 ///     メッシュに基本情報(頂点座標・法線・UV・ボーンウェイト)を登録する
 /// </summary>
 /// <param name='mesh'>対象メッシュ</param>
 /// <param name='creation_info'>メッシュ作成情報</param>
 private void EntryAttributesForMesh(Mesh mesh, MeshCreationInfo creation_info)
 {
     mesh.vertices = creation_info.all_vertices.Select(x => format_.vertex_list.vertex[x].pos * scale_)
                     .ToArray();
     mesh.normals = creation_info.all_vertices.Select(x => format_.vertex_list.vertex[x].normal_vec).ToArray();
     mesh.uv      = creation_info.all_vertices.Select(x => format_.vertex_list.vertex[x].uv).ToArray();
     if (0 < format_.header.additionalUV)
     {
         //追加UVが1つ以上有れば
         //1つ目のみ登録
         mesh.uv2 = creation_info.all_vertices.Select(x => new Vector2(format_.vertex_list.vertex[x].add_uv[0].x,
                                                                       format_.vertex_list.vertex[x].add_uv[0].y)).ToArray();
     }
     mesh.boneWeights = creation_info.all_vertices
                        .Select(x => ConvertBoneWeight(format_.vertex_list.vertex[x].bone_weight)).ToArray();
     mesh.colors = creation_info.all_vertices.Select(x =>
                                                     new Color(0.0f, 0.0f, 0.0f, format_.vertex_list.vertex[x].edge_magnification * 0.25f))
                   .ToArray(); //不透明度にエッジ倍率を0.25倍した情報を仕込む(0~8迄は表せる)
 }
Пример #6
0
        /// <summary>
        /// マテリアルをProjectに登録する
        /// </summary>
        /// <param name='mesh'>対象マテリアル</param>
        /// <param name='creation_info'>メッシュ作成情報</param>
        void CreateAssetForMaterials(Material[] materials, MeshCreationInfo creation_info)
        {
            // 適当なフォルダに投げる
            string path = format_.meta_header.folder + "/Materials/";
            if (!System.IO.Directory.Exists(path)) {
                AssetDatabase.CreateFolder(format_.meta_header.folder, "Materials");
            }

            for (int i = 0, i_max = materials.Length; i < i_max; ++i) {
                uint material_index = creation_info.value[i].material_index;
                string name = GetFilePathString(format_.material_list.material[material_index].name);
                string file_name = path + material_index.ToString() + "_" + name + ".asset";
                AssetDatabase.CreateAsset(materials[i], file_name);
            }
        }
Пример #7
0
		/// <summary>
		/// 1マテリアルの頂点数が1メッシュで表現出来ないので分割する
		/// </summary>
		/// <returns>メッシュ作成情報のマテリアルパック</returns>
		/// <param name='creation_infos'>メッシュ作成情報のマテリアルパック</param>
		List<MeshCreationInfo.Pack> SplitSubMesh(MeshCreationInfo.Pack pack)
		{
			List<MeshCreationInfo.Pack> result = new List<MeshCreationInfo.Pack>();
			//1メッシュに収まらないなら
			uint plane_end = (uint)pack.plane_indices.Length;
			uint plane_start = 0;
			while (plane_start < plane_end) {
				//まだ面が有るなら
				uint plane_count = 0;
				uint vertex_count = 0;
				while (true) {
					//現在の頂点数から考えると、余裕分の1/3迄の数の面は安定して入る
					//はみ出て欲しいから更に1面(3頂点)を足す
					plane_count += (c_max_vertex_count_in_mesh - vertex_count) / 3 * 3 + 3;
					vertex_count = (uint)pack.plane_indices.Skip((int)plane_start)	//面頂点インデックス取り出し(先頭)
															.Take((int)plane_count)	//面頂点インデックス取り出し(末尾)
															.Distinct()				//重複削除
															.Count();				//個数取得
					if (c_max_vertex_count_in_mesh <= vertex_count) {
						//1メッシュを超えているなら
						//此処でのメッシュ超えは必ずc_max_vertex_count_in_meshぎりぎりで有り、1面(3頂点)を1つ取れば収まる様になっている
						plane_count -= 3;
						break;
					}
					if (plane_end <= (plane_start + plane_count)) {
						//面の最後なら
						break;
					}
				}
				//分離分を戻り値の追加
				MeshCreationInfo.Pack result_pack = new MeshCreationInfo.Pack();;
				result_pack.material_index = pack.material_index;
				result_pack.plane_indices = pack.plane_indices.Skip((int)plane_start)	//面頂点インデックス取り出し(先頭)
																.Take((int)plane_count)	//面頂点インデックス取り出し(末尾)
																.ToArray();
				result_pack.vertices = result_pack.plane_indices.Distinct()	//重複削除
																.ToArray();
				result.Add(result_pack);
				//開始点を後ろに
				plane_start += plane_count;
			}
			return result;
		}
Пример #8
0
        /// <summary>
        /// モーフ作成
        /// </summary>
        /// <param name='mesh'>対象メッシュ</param>
        /// <param name='materials'>対象マテリアル</param>
        /// <param name='bones'>対象ボーン</param>
        /// <param name='renderers'>対象レンダラー</param>
        /// <param name='creation_info'>メッシュ作成情報</param>
        void CreateMorph(Mesh[] mesh, Material[][] materials, GameObject[] bones, SkinnedMeshRenderer[] renderers, MeshCreationInfo[] creation_info)
        {
            //表情ルートを生成してルートの子供に付ける
            GameObject expression_root = new GameObject("Expression");
            Transform expression_root_transform = expression_root.transform;
            expression_root_transform.parent = root_game_object_.transform;

            //表情マネージャー
            MorphManager morph_manager = expression_root.AddComponent<MorphManager>();
            morph_manager.uv_morph = new MorphManager.UvMorphPack[1 + format_.header.additionalUV]; //UVモーフ数設定

            //個別モーフスクリプト作成
            GameObject[] morphs = new GameObject[format_.morph_list.morph_data.Length];
            for (int i = 0, i_max = format_.morph_list.morph_data.Length; i < i_max; ++i) {
                morphs[i] = new GameObject(format_.morph_list.morph_data[i].morph_name);
                // 表情を親ボーンに付ける
                morphs[i].transform.parent = expression_root_transform;
            }

            //グループモーフ作成
            CreateGroupMorph(morph_manager, morphs);
            //ボーンモーフ
            morph_manager.bones = bones.Select(x=>x.transform).ToArray();
            CreateBoneMorph(morph_manager, morphs);
            //頂点モーフ作成
            CreateVertexMorph(morph_manager, morphs, creation_info);
            //UV・追加UVモーフ作成
            CreateUvMorph(morph_manager, morphs, creation_info);
            //材質モーフ作成
            CreateMaterialMorph(morph_manager, morphs, creation_info);
            //モーフ一覧設定(モーフコンポーネントの情報を拾う為、最後に設定する)
            morph_manager.morphs = morphs.Select(x=>x.GetComponent<MorphBase>()).ToArray();

            //メッシュ・マテリアル設定
            morph_manager.renderers = renderers;
            morph_manager.mesh = mesh;
            morph_manager.materials = materials;
        }
Пример #9
0
        /// <summary>
        /// メッシュを作成する為の情報を作成(複数メッシュ版)
        /// </summary>
        /// <returns>メッシュ作成情報</returns>
        MeshCreationInfo[] CreateMeshCreationInfoMulti()
        {
            //マテリアル単位のMeshCreationInfo.Packを作成する
            MeshCreationInfo.Pack[] packs = CreateMeshCreationInfoPacks();
            //頂点数の多い順に並べる(メッシュ分割アルゴリズム上、後半に行く程頂点数が少ない方が敷き詰め効率が良い)
            System.Array.Sort(packs, (x,y)=>y.vertices.Length - x.vertices.Length);

            List<MeshCreationInfo> result = new List<MeshCreationInfo>();
            do {
                uint vertex_sum = 0;
                MeshCreationInfo info = new MeshCreationInfo();
                //マテリアルパック作成
                info.value = Enumerable.Range(0, packs.Length)
                                        .Where(x=>null!=packs[x]) //有効なマテリアルに絞る
                                        .Where(x=>{	//採用しても頂点数が限界を超えないなら
                                                    vertex_sum += (uint)packs[x].vertices.Length;
                                                    return vertex_sum < c_max_vertex_count_in_mesh;
                                                })
                                        .Select(x=>{	//マテリアルの採用と無効化
                                                    var pack = packs[x];
                                                    packs[x] = null;
                                                    return pack;
                                                })
                                        .ToArray();
                //マテリアルインデックスに並べる(メッシュの選定が終わったので見易い様に並びを戻す)
                System.Array.Sort(info.value, (x,y)=>((x.material_index>y.material_index)? 1: (x.material_index<y.material_index)? -1: 0));
                //総頂点作成
                info.all_vertices = info.value.SelectMany(x=>x.vertices).Distinct().ToArray();
                System.Array.Sort(info.all_vertices);
                //頂点リアサインインデックス用辞書作成
                info.reassign_dictionary = new Dictionary<uint, uint>();
                uint reassign_index = 0;
                foreach (var i in info.all_vertices) {
                    info.reassign_dictionary[i] = reassign_index++;
                }
                //戻り値に追加
                result.Add(info);
            } while (packs.Any(x=>null!=x)); //使用していないマテリアルが為るならループ
            return result.ToArray();
        }
Пример #10
0
 /// <summary>
 /// メッシュ作成
 /// </summary>
 /// <returns>メッシュ</returns>
 /// <param name='creation_info'>メッシュ作成情報</param>
 Mesh[] CreateMesh(MeshCreationInfo[] creation_info)
 {
     Mesh[] result = new Mesh[creation_info.Length];
     for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) {
         Mesh mesh = new Mesh();
         EntryAttributesForMesh(mesh, creation_info[i]);
         SetSubMesh(mesh, creation_info[i]);
         CreateAssetForMesh(mesh, i);
         result[i] = mesh;
     }
     return result;
 }
Пример #11
0
 /// <summary>
 /// マテリアル作成
 /// </summary>
 /// <returns>マテリアル</returns>
 /// <param name='creation_info'>メッシュ作成情報</param>
 Material[][] CreateMaterials(MeshCreationInfo[] creation_info)
 {
     Material[][] result = new Material[creation_info.Length][];
     for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) {
         Material[] materials = EntryAttributesForMaterials(creation_info[i]);
         CreateAssetForMaterials(materials, creation_info[i]);
         result[i] = materials;
     }
     return result;
 }
Пример #12
0
		/// <summary>
		/// 1マテリアルの頂点数が1メッシュで表現出来ない場合に分割する
		/// </summary>
		/// <returns>メッシュ作成情報のマテリアルパック</returns>
		/// <param name='creation_infos'>メッシュ作成情報のマテリアルパック</param>
		MeshCreationInfo.Pack[] SplitSubMesh(MeshCreationInfo.Pack[] packs)
		{
			MeshCreationInfo.Pack[] result = packs;
			if (packs.Any(x=>c_max_vertex_count_in_mesh<=x.vertices.Length)) {
				//1メッシュに収まらないマテリアルが有るなら
				List<MeshCreationInfo.Pack> result_list = new List<MeshCreationInfo.Pack>();
				foreach (var pack in packs) {
					if (c_max_vertex_count_in_mesh <= pack.vertices.Length) {
						//1メッシュに収まらないなら
						//分離
						var split_pack = SplitSubMesh(pack);
						foreach (var i in split_pack) {
							result_list.Add(i);
						}
					} else {
						//1メッシュに収まるなら
						//素通し
						result_list.Add(pack);
					}
				}
				result = result_list.ToArray();
			}
			return result;
		}
Пример #13
0
 /// <summary>
 /// メッシュにサブメッシュを登録する
 /// </summary>
 /// <param name='mesh'>対象メッシュ</param>
 /// <param name='creation_info'>メッシュ作成情報</param>
 void SetSubMesh(Mesh mesh, MeshCreationInfo creation_info)
 {
     // マテリアル対サブメッシュ
     // サブメッシュとはマテリアルに適用したい面頂点データのこと
     // 面ごとに設定するマテリアルはここ
     mesh.subMeshCount = creation_info.value.Length;
     for (int i = 0, i_max = creation_info.value.Length; i < i_max; ++i) {
         //format_.face_vertex_list.face_vert_indexを[start](含む)から[start+count](含まず)迄取り出し
         int[] indices = format_.face_vertex_list.face_vert_index.Skip((int)creation_info.value[i].plane_start)
                                                                 .Take((int)creation_info.value[i].plane_count)
                                                                 .Select(x=>(int)creation_info.reassign_dictionary[x]) //頂点リアサインインデックス変換
                                                                 .ToArray();
         mesh.SetTriangles(indices, i);
     }
 }
Пример #14
0
 /// <summary>
 /// メッシュに基本情報(頂点座標・法線・UV・ボーンウェイト)を登録する
 /// </summary>
 /// <param name='mesh'>対象メッシュ</param>
 /// <param name='creation_info'>メッシュ作成情報</param>
 void EntryAttributesForMesh(Mesh mesh, MeshCreationInfo creation_info)
 {
     mesh.vertices = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].pos * scale_).ToArray();
     mesh.normals = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].normal_vec).ToArray();
     mesh.uv = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].uv).ToArray();
     if (0 < format_.header.additionalUV) {
         //追加UVが1つ以上有れば
         //1つ目のみ登録
         mesh.uv2 = creation_info.all_vertices.Select(x=>new Vector2(format_.vertex_list.vertex[x].add_uv[0].x, format_.vertex_list.vertex[x].add_uv[0].y)).ToArray();
     }
     mesh.boneWeights = creation_info.all_vertices.Select(x=>ConvertBoneWeight(format_.vertex_list.vertex[x].bone_weight)).ToArray();
     mesh.colors = creation_info.all_vertices.Select(x=>new Color(0.0f, 0.0f, 0.0f, format_.vertex_list.vertex[x].edge_magnification * 0.25f)).ToArray(); //不透明度にエッジ倍率を0.25倍した情報を仕込む(0~8迄は表せる)
 }
Пример #15
0
 /// <summary>
 /// マテリアルに基本情報(シェーダー・カラー・テクスチャ)を登録する
 /// </summary>
 /// <returns>マテリアル</returns>
 /// <param name='creation_info'>メッシュ作成情報</param>
 Material[] EntryAttributesForMaterials(MeshCreationInfo creation_info)
 {
     return creation_info.value.Select(x=>ConvertMaterial(format_.material_list.material[x.material_index]))
                                 .ToArray();
 }
Пример #16
0
        /// <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);
        }
Пример #17
0
        /// <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);
            }
        }
Пример #18
0
		/// <summary>
		/// マテリアル作成
		/// </summary>
		/// <returns>マテリアル</returns>
		/// <param name='creation_info'>メッシュ作成情報</param>
		Material[][] CreateMaterials(MeshCreationInfo[] creation_info)
		{
			// 適当なフォルダに投げる
			string path = format_.meta_header.folder + "/Materials/";
			if (!System.IO.Directory.Exists(path)) { 
				AssetDatabase.CreateFolder(format_.meta_header.folder, "Materials");
			}
			
			//全マテリアルを作成
			Material[] materials = EntryAttributesForMaterials();
			CreateAssetForMaterials(materials);

			//メッシュ単位へ振り分け
			Material[][] result = new Material[creation_info.Length][];
			for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) {
				result[i] = creation_info[i].value.Select(x=>materials[x.material_index]).ToArray();
			}

			return result;
		}
Пример #19
0
        /// <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>
        /// Gets the thumbnail image
        /// </summary>
        /// <param name="width">The width of the image that should be returned.</param>
        /// <returns>
        /// The image for the thumbnail
        /// </returns>
        protected override Bitmap GetThumbnailImage(uint width)
        {
            //  Attempt to open the stream with a reader
            var pmx = PMXLoaderScript.Import(SelectedItemPath);

            MeshCreationInfo creation_info = CreateMeshCreationInfoSingle(pmx);

            var diffuseMat = MaterialHelper.CreateMaterial(Colors.Gray);

            var models = new Model3DGroup();

            for (int i = 0, i_max = creation_info.value.Length; i < i_max; ++i)
            {
                int[] indices = creation_info.value[i].plane_indices.Select(x => (int)creation_info.reassign_dictionary[x])
                                .ToArray();
                var mesh = new MeshGeometry3D
                {
                    Positions = new Point3DCollection(pmx.vertex_list.vertex.Select(x => x.pos)),

                    TextureCoordinates = new PointCollection(pmx.vertex_list.vertex.Select(x => new System.Windows.Point(x.uv.X, x.uv.Y)))
                };



                indices.ToList()
                .ForEach(x => mesh.TriangleIndices.Add(x));
                var textureIndex = pmx.material_list.material[creation_info.value[i].material_index].usually_texture_index;
                var texturePath  = pmx.texture_list.texture_file.ElementAtOrDefault((int)textureIndex);

                var material = diffuseMat;
                if (!string.IsNullOrWhiteSpace(texturePath))
                {
                    texturePath = Path.Combine(Path.GetDirectoryName(SelectedItemPath), texturePath);
                    //Log($"Texture found: {texturePath}");

                    if (!string.IsNullOrWhiteSpace(texturePath) && File.Exists(texturePath))
                    {
                        //  dds and tga
                        if (new string[] { ".dds", ".tga" }.Any(x => x.Equals(Path.GetExtension(texturePath))))
                        {
                            var bitmap = PFimToBitmap(texturePath);
                            material = MaterialHelper.CreateImageMaterial(Bitmap2BitmapImage(bitmap), 1);
                        }
                        else
                        {
                            material = MaterialHelper.CreateImageMaterial(BitmapImageFromFile(texturePath), 1);
                        }
                    }
                }

                models.Children.Add(new GeometryModel3D(mesh, material));
            }

            var sorting = new SortingVisual3D()
            {
                Content = models
            };

            var view = new HelixViewport3D();

            view.Children.Add(sorting);
            view.Camera.Position      = new Point3D(0, 15, -30);
            view.Camera.LookDirection = new Vector3D(0, -5, 30);

            view.Background = System.Windows.Media.Brushes.Transparent;

            view.Children.Add(new SunLight()
            {
                Altitude = 260
            });

            view.Children.Add(new DefaultLights());

            try
            {
                var bitmap = view.Viewport.RenderBitmap(width, width, new SolidColorBrush(Colors.Transparent));
                view.Children.Clear();
                view    = null;
                sorting = null;
                models  = null;
                GC.Collect();
                return(BitmapFromSource(bitmap));
            }
            catch (Exception exception)
            {
                view.Children.Clear();
                view    = null;
                sorting = null;
                models  = null;
                GC.Collect();
                LogError("An exception occurred Rendering bitmap.", exception);
                //MessageBox.Show(exception.Message);
                //MessageBox.Show(exception.StackTrace);
                return(null);
            }
        }