Пример #1
0
 public DrawableMaterial(IPXMaterial material, int indexOffset)
 {
     Visible        = true;
     OriginMaterial = material;
     IndexOffset    = indexOffset;
     Textures       = new ShaderResourceView[(int)TKind.NUM];
 }
Пример #2
0
        /// <summary>
        /// 材質設定
        /// </summary>
        private void SetMaterial()
        {
            message.LabelReflesh("モデル読み込み: 材質");
            message.StatusBar.Value   = 0;
            message.StatusBar.Maximum = pmx.Material.Count;
            int facestart = 0;

            for (int matidx = 0; matidx < this.pmx.Material.Count; matidx++)
            {
                IPXMaterial mat = this.pmx.Material[matidx];
                this.AttributeRanges[matidx]           = new AttributeRange();
                this.AttributeRanges[matidx].AttribId  = matidx;
                this.AttributeRanges[matidx].FaceCount = mat.Faces.Count;
                this.AttributeRanges[matidx].FaceStart = facestart;
                facestart += mat.Faces.Count;
                this.AttributeRanges[matidx].VertexCount = this.GetUsedVertexList(matidx).Count;
                this.AttributeRanges[matidx].VertexStart = pmx.Vertex.IndexOf(mat.Faces[0].Vertex1);

                this.Exmaterials[matidx] = new ExtendedMaterial();
                this.Exmaterials[matidx].TextureFileName = mat.Tex;
                Material tmpmat = new Material();
                tmpmat.Ambient  = new Color4(mat.Diffuse.A, mat.Ambient.R, mat.Ambient.G, mat.Ambient.B);
                tmpmat.Diffuse  = mat.Diffuse.ToColor4();
                tmpmat.Power    = mat.Power;
                tmpmat.Specular = new Color4(mat.Specular.ToColor3());
                this.Exmaterials[matidx].MaterialD3D = tmpmat;
                message.StatusBar.Value++;
            }
        }
Пример #3
0
        private ExtendedMaterial[] InitMaterialArray(Dictionary <IPXVertex, int> vDic)
        {
            ExtendedMaterial[] ExMaterialArray = new ExtendedMaterial[Pmx.Material.Count];
            ARangeArray     = new AttributeRange[Pmx.Material.Count];
            ExMaterialArray = new ExtendedMaterial[Pmx.Material.Count];
            int faceOffset = 0;

            for (int i = 0; i < Pmx.Material.Count; i++)
            {
                IPXMaterial m = Pmx.Material[i];
                ARangeArray[i] = new AttributeRange
                {
                    AttribId    = i,
                    FaceCount   = m.Faces.Count,
                    FaceStart   = faceOffset,
                    VertexCount = VIndices[i].Count,
                    VertexStart = vDic[m.Faces[0].Vertex1]
                };
                faceOffset        += m.Faces.Count;
                ExMaterialArray[i] = new ExtendedMaterial
                {
                    MaterialD3D = new Material
                    {
                        //Ambient = new Color4(1,m.Ambient.R,m.Ambient.G,m.Ambient.B),
                        Emissive = new Color4(1, m.Ambient.R, m.Ambient.G, m.Ambient.B),
                        Diffuse  = m.Diffuse.ToColor4(),
                        Power    = m.Power,
                        Specular = new Color4(m.Specular.ToColor3())
                    },
                    TextureFileName = m.Tex
                };
            }
            return(ExMaterialArray);
        }
Пример #4
0
        /// <summary>
        /// 材質内のすべての面を頂点インデックス配列に変換
        /// </summary>
        /// <param name="material">変換する諸面の材質</param>
        /// <param name="pmx">頂点を内包したPMXデータ</param>
        /// <returns>材質内の全ての面を構成する頂点のインデックス配列</returns>
        public static IEnumerable <int[]> FaceToVertexIndices(this IPXMaterial material, IPXPmx pmx)
        {
            var vtxIds = pmx.Vertex.Select((v, i) => (v, i)).ToDictionary(p => p.v, p => p.i);

            foreach (var face in material.Faces)
            {
                yield return(new int[] { vtxIds[face.Vertex1], vtxIds[face.Vertex2], vtxIds[face.Vertex3] });
            }
        }
Пример #5
0
            /// <summary>
            /// Returns the vertices of the specified material.
            /// </summary>
            public static IEnumerable <IPXVertex> FromMaterial(IPXMaterial material)
            {
                HashSet <IPXVertex> vertices = new HashSet <IPXVertex>();

                foreach (IPXFace face in material.Faces)
                {
                    vertices.Add(face.Vertex1);
                    vertices.Add(face.Vertex2);
                    vertices.Add(face.Vertex3);
                }
                return(vertices);
            }
Пример #6
0
        Bitmap GetMeshImage(IPXMaterial material, bool withLine = true)
        {
            if (bitmap == null)
            {
                return(null);
            }
            V2 Scale(V2 v)
            {
                return(new V2(U(v.U), V(v.V)));
            }

            Rectangle VertexSquare(V2 vertex, int size)
            {
                Rectangle square = new Rectangle();

                square.X      = (int)Math.Round(U(vertex.U) - (size - 1) / 2, MidpointRounding.AwayFromZero);
                square.Y      = (int)Math.Round(V(vertex.V) - (size - 1) / 2, MidpointRounding.AwayFromZero);
                square.Width  = size;
                square.Height = size;
                return(square);
            }

            Bitmap map  = new Bitmap(bitmap.Width, bitmap.Height);
            var    mesh = new PXMesh(material);

            using (Graphics graphics = Graphics.FromImage(map))
            {
                int penWidth   = (int)numericWidth.Value;
                int squareSize = (int)numericWidth.Value * 3;

                if (withLine)
                {
                    foreach (var s in mesh.Sides)
                    {
                        using (Pen pen = new Pen(Color.Black, penWidth))
                        {
                            graphics.DrawLine(pen, Scale(s.VertexPair[0].UV).ToPointF(), Scale(s.VertexPair[1].UV).ToPointF());
                        }
                    }
                }
                foreach (IPXVertex v in mesh.Vertices)
                {
                    using (Pen pen = new Pen(GetPointColor(v)))
                    {
                        graphics.FillRectangle(pen.Brush, VertexSquare(v.UV, squareSize));
                    }
                }
            }
            return(map);
        }
Пример #7
0
 public void SetMaterial(IPXMaterial material, ShaderResourceView[] textures)
 {
     if (material != null)
     {
         SetVariable("diffuse", "geometry", material.Diffuse.ToVector4());
         SetVariable("ambient", "geometry", V4ToVector3(material.Diffuse));
         SetVariable("emissive", "geometry", material.Ambient.ToVector3());
         SetVariable("specular", "geometry", material.Specular.ToVector3());
         SetVariable("specularpower", "geometry", material.Power);
     }
     SetVariable("materialtexture", "", textures[(int)TexKind.OBJ]);
     SetVariable("materialtoontexture", "", textures[(int)TexKind.TOON]);
     SetVariable("materialspheremap", "", textures[(int)TexKind.SPHERE]);
 }
Пример #8
0
        public Material(IPXMaterial material, IPXPmx pmx)
        {
            InstanceId = instanceCount;
            instanceCount++;

            Value     = material;
            ModelPath = pmx.FilePath;
            CreateTexFullPath();

            IEnumerable <IPXVertex> faceVertices = Faces.SelectMany(face => face.ToVertices());

            Vertices   = faceVertices.Distinct().ToList();
            IsSelected = Vertices.ToDictionary(vtx => vtx, _ => false);
            TemporaryTransformMatrices = Matrix.Identity;

            var VtxIdDic = Vertices.Select((vtx, i) => (vtx, i)).ToDictionary(pair => pair.vtx, pair => (uint)pair.i);

            FaceSequence = faceVertices.Select(vtx => VtxIdDic[vtx]).ToArray();
        }
Пример #9
0
        private void buttonRun_Click(object sender, EventArgs e)
        {
            var selectedMaterialID = listBoxMaterial.SelectedIndex - 1;

            if (selectedMaterialID < 0)
            {
                MessageBox.Show("ウェイト転写対象の材質を選択してください。");
                return;
            }
            if (comboBoxBone.SelectedIndex < 0)
            {
                MessageBox.Show("ウェイト対象のボーンを選択してください。");
                return;
            }

            pmx = args.Host.Connector.Pmx.GetCurrentState();
            IPXMaterial targetMaterial = pmx.Material[selectedMaterialID];
            IPXBone     targetBone     = pmx.Bone[comboBoxBone.SelectedIndex];

            var mesh = new PXMesh(targetMaterial);

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                IPXVertex v = mesh.Vertices[i];
                (IPXBone bone, float weight)bw = (targetBone, GetPointColor(v).R / 255f);
                var vertexWB = Utility.GetWeights(v);

                //頂点のウェイトを編集
                vertexWB.RemoveAll(w => w.bone == bw.bone);
                Utility.NormalizeWeights(vertexWB, 1 - bw.weight);
                vertexWB.Add(bw);
                Utility.SetVertexWeights(vertexWB, ref v);
            }

            Utility.Update(args.Host.Connector, pmx, PmxUpdateObject.Vertex);
            MessageBox.Show("完了");
        }
Пример #10
0
        /// <summary>
        /// Parses the Material Template Library at the provided path and returns a list of materials.
        /// </summary>
        private static Dictionary <string, IPXMaterial> ImportMaterials(string path, IPXPmxBuilder builder, ImportSettings settings, IOProgress progress)
        {
            // Cancel the process if needed
            if (progress.CancellationToken.IsCancellationRequested)
            {
                progress.CancellationToken.ThrowIfCancellationRequested();
            }

            StreamReader reader = null;

            System.Globalization.NumberFormatInfo fi = System.Globalization.NumberFormatInfo.InvariantInfo;
            System.Globalization.NumberStyles     ns = System.Globalization.NumberStyles.Float;

            Dictionary <string, IPXMaterial> materials = new Dictionary <string, IPXMaterial>();
            IPXMaterial current    = null;
            int         lineNumber = 0;

            char[] separator = { ' ' };

            try
            {
                reader = new StreamReader(path);
                while (!reader.EndOfStream)
                {
                    // Cancel the process if needed
                    if (progress.CancellationToken.IsCancellationRequested)
                    {
                        progress.CancellationToken.ThrowIfCancellationRequested();
                    }

                    string line = reader.ReadLine().Trim();
                    ++lineNumber;
                    if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                    {
                        continue;
                    }
                    string[] split = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    switch (split[0])
                    {
                    // Diffuse color and opacity
                    case "Kd":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0, a = 1;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            if (split.Length > 4)
                            {
                                float.TryParse(split[4], ns, fi, out a);
                            }

                            current.Diffuse = new V4(r, g, b, a);
                        }
                        break;

                    // Ambient - used as emissive
                    case "Ka":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Ambient = new V3(r, g, b);
                        }
                        break;

                    // Specular color
                    case "Ks":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Specular = new V3(r, g, b);
                        }
                        break;

                    // Emissive
                    case "Ke":
                        if (current != null)
                        {
                            float r = 0, g = 0, b = 0;
                            float.TryParse(split[1], ns, fi, out r);
                            float.TryParse(split[2], ns, fi, out g);
                            float.TryParse(split[3], ns, fi, out b);
                            current.Ambient = new V3(r, g, b);
                        }
                        break;

                    // Opacity (1 is fully opaque)
                    case "d":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Diffuse.A = a;
                            }
                        }
                        break;

                    // Transparency (1 is fully transparent)
                    case "Tr":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Diffuse.A = 1.0f - a;
                            }
                        }
                        break;

                    // Specular exponent
                    case "Ns":
                        if (current != null)
                        {
                            if (float.TryParse(split[1], ns, fi, out float a))
                            {
                                current.Power = a;
                            }
                        }
                        break;

                    // Illumination mode (unused)
                    case "illum":
                        break;

                    // Diffuse map
                    case "map_Kd":
                        if (current != null)
                        {
                            current.Tex = line.Substring(7);
                            if (settings.WhiteMaterialIfTextured)
                            {
                                current.Diffuse = new V4(1, 1, 1, current.Diffuse.A);
                                current.Ambient = new V3(0.5f, 0.5f, 0.5f);
                            }
                        }
                        break;

                    // Specular map
                    case "map_Ks":
                        break;

                    // Ambient map
                    case "map_Ka":
                        break;

                    // Begin a new material
                    case "newmtl":
                        current               = builder.Material();
                        current.Name          = current.NameE = line.Substring(7);
                        current.Diffuse       = new V4(1, 1, 1, 1);
                        current.Ambient       = new V3(0.5f, 0.5f, 0.5f);
                        current.Specular      = new V3(0, 0, 0);
                        current.Power         = 20;
                        current.SelfShadow    = true;
                        current.SelfShadowMap = true;
                        current.Shadow        = true;
                        current.BothDraw      = false;

                        if (materials.ContainsKey(current.Name))
                        {
                            progress.ReportWarning(string.Format("[MTL {1}] Duplicate material found: \"{0}\".", current.Name, lineNumber));
                        }
                        else
                        {
                            materials.Add(current.Name, current);
                        }

                        break;

                    default:
                        break;
                    }
                }
            }
            catch (OperationCanceledException) { throw; }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }

            return(materials);
        }
Пример #11
0
        /// <summary>
        /// Parses the Wavefront Object file at the provided path and returns the operation's result.
        /// </summary>
        public static ImportResult Import(string path, IPXPmxBuilder builder, ImportSettings settings, IOProgress progress)
        {
            // Cancel the process if needed
            if (progress.CancellationToken.IsCancellationRequested)
            {
                progress.CancellationToken.ThrowIfCancellationRequested();
            }

            IPXPmx pmx = builder.Pmx();

            pmx.Clear();
            pmx.ModelInfo.ModelName = pmx.ModelInfo.ModelNameE = Path.GetFileNameWithoutExtension(path);
            pmx.ModelInfo.Comment   = pmx.ModelInfo.CommentE = "(Imported from OBJ by WPlugins.ObjIO)";
            StreamReader reader = null;

            System.Globalization.NumberFormatInfo fi = System.Globalization.NumberFormatInfo.InvariantInfo;
            System.Globalization.NumberStyles     ns = System.Globalization.NumberStyles.Float;

            // Model elements
            List <V3> vList  = new List <V3>();
            List <V2> vtList = new List <V2>();
            List <V3> vnList = new List <V3>();
            Dictionary <Tuple <int, int, int>, int> vertexDictionary = new Dictionary <Tuple <int, int, int>, int>();
            Dictionary <string, IPXMaterial>        materials        = new Dictionary <string, IPXMaterial>();
            IPXMaterial currentMaterial = null;

            // Values derived from settings
            V3 positionScale = new V3(settings.ScaleX, settings.ScaleY, settings.ScaleZ) * (settings.UseMetricUnits ? 0.254f : 0.1f);

            // Statistics
            int lineNumber = 0;

            try
            {
                reader = new StreamReader(path);
                char[] separator = { ' ' };
                while (!reader.EndOfStream)
                {
                    System.Threading.Thread.Sleep(2);

                    // Cancel the process if needed
                    if (progress.CancellationToken.IsCancellationRequested)
                    {
                        progress.CancellationToken.ThrowIfCancellationRequested();
                    }

                    string line = reader.ReadLine().Trim();
                    ++lineNumber;
                    ++progress.LineNumber;
                    progress.Report(IOProgress.Percent(reader.BaseStream.Position, reader.BaseStream.Length));

                    // Skip empty lines and comments
                    if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                    {
                        continue;
                    }

                    string[] split = line.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    switch (split[0])
                    {
                    // Vertex position
                    case "v":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vList.Add(new V3());
                        }
                        break;

                    // Vertex texture coordinates
                    case "vt":
                        try
                        {
                            // Technically this can be a V3 or any vector, but PMX only uses the first two elements for the main UV channel.
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            vtList.Add(new V2(x, -y));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vtList.Add(new V2());
                        }
                        break;

                    // Vertex normal
                    case "vn":
                        try
                        {
                            float x = float.Parse(split[1], ns, fi);
                            float y = float.Parse(split[2], ns, fi);
                            float z = float.Parse(split[3], ns, fi);
                            vnList.Add(new V3(x, y, -z));
                        }
                        catch (FormatException ex)
                        {
                            if (progress.ReportError(string.Format("A format exception has occured: {0}", line)))
                            {
                                return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                            }
                            vnList.Add(new V3());
                        }
                        break;

                    // Face definition
                    case "f":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a face record when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }

                        // Triangle
                        if (split.Length == 4)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;

                            try
                            {
                                // Split each vertex assignment triple into its respective v/vt/vn indices.
                                GetVertexElements(split[1], out v, out vt, out vn);
                                // Based on the indices, determine if the vertex assignment is unique or already exists. A vertex is considered unique if one or more index is different, regardless of the vectors they represent.
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);       // The new vertex is added to the end of the list, making its index equal to the list's count before the addition.
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                // Repeat the same process for the rest of the vertex triples.
                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                // Build the triangle and assign the vertices; use reverse order and negative normal vectors if the triangles are reversed.
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    vertex1.Normal *= -1;
                                    vertex2.Normal *= -1;
                                    vertex3.Normal *= -1;
                                    face.Vertex1    = vertex1;
                                    face.Vertex2    = vertex2;
                                    face.Vertex3    = vertex3;
                                }
                                else
                                {
                                    face.Vertex1 = vertex3;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                }
                                currentMaterial.Faces.Add(face);
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        // Quad
                        else if (split.Length == 5)
                        {
                            int  v  = 0;
                            int  vt = 0;
                            int  vn = 0;
                            bool newVertex;
                            try
                            {
                                GetVertexElements(split[1], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index1);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex1 = pmx.Vertex[index1];

                                GetVertexElements(split[2], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index2);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex2 = pmx.Vertex[index2];

                                GetVertexElements(split[3], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index3);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex3 = pmx.Vertex[index3];

                                GetVertexElements(split[4], out v, out vt, out vn);
                                newVertex = GetUniqueVertex(v, vt, vn, vertexDictionary, pmx.Vertex.Count, out int index4);
                                if (newVertex)
                                {
                                    IPXVertex vert = builder.Vertex();
                                    pmx.Vertex.Add(vert);
                                    if (v >= 0)
                                    {
                                        vert.Position = vList[v] * positionScale;
                                    }
                                    if (vt >= 0)
                                    {
                                        vert.UV = vtList[vt];
                                    }
                                    if (vn >= 0)
                                    {
                                        vert.Normal = vnList[vn];
                                    }
                                }
                                IPXVertex vertex4 = pmx.Vertex[index4];

                                int     faceIndex1 = 0, faceIndex2 = 0;
                                IPXFace face = builder.Face();
                                if (settings.FlipFaces)
                                {
                                    face.Vertex3 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex1 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex1 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex3 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }
                                else
                                {
                                    face.Vertex1 = settings.TurnQuads ? vertex3 : vertex4;
                                    face.Vertex2 = vertex2;
                                    face.Vertex3 = vertex1;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex1 = currentMaterial.Faces.Count - 1;

                                    face         = builder.Face();
                                    face.Vertex3 = settings.TurnQuads ? vertex1 : vertex2;
                                    face.Vertex2 = vertex3;
                                    face.Vertex1 = vertex4;
                                    currentMaterial.Faces.Add(face);
                                    faceIndex2 = currentMaterial.Faces.Count - 1;
                                }

                                if (settings.SaveTrianglePairs)
                                {
                                    currentMaterial.Memo += string.Format("({0},{1})", faceIndex1, faceIndex2);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (progress.ReportError(ex.ToString()))
                                {
                                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                                }
                            }
                        }
                        else
                        {
                            if (progress.ReportError(string.Format("The OBJ file contains a polygon with an invalid number of vertices. Currently only triangles and quads are supported. Line content: {0}", line)))
                            {
                                return(ImportResult.Fail(new InvalidOperationException("Invalid polygon"), progress.WarningCount, progress.ErrorCount));
                            }
                        }
                        break;

                    // Group assignment defines which PMX object (IPXMaterial instance) the subsequent faces belong to.
                    case "g":
                        currentMaterial      = builder.Material();
                        currentMaterial.Name = currentMaterial.NameE = line.Trim().Substring(2);
                        progress.Report("New object: " + currentMaterial.Name);
                        pmx.Material.Add(currentMaterial);
                        // Set default properties
                        currentMaterial.Diffuse = new V4(1, 1, 1, 1);
                        currentMaterial.Ambient = new V3(0.5f, 0.5f, 0.5f);
                        break;

                    // Material assignment defines which material template should be applied to the currently active PMX object. Any number of PMX objects can refer to a single material template.
                    case "usemtl":
                        if (currentMaterial == null)
                        {
                            progress.ReportWarning(string.Format("Encountered a material template reference when no active group was set.", lineNumber));
                            currentMaterial = builder.Material();
                        }
                        {
                            string      name = line.Trim().Substring(7);
                            IPXMaterial m    = currentMaterial;     // Active material
                            IPXMaterial t    = materials[name];     // Template material
                            m.Diffuse       = t.Diffuse;
                            m.Specular      = t.Specular;
                            m.Power         = t.Power;
                            m.Ambient       = t.Ambient;
                            m.Diffuse       = t.Diffuse;
                            m.SelfShadow    = t.SelfShadow;
                            m.SelfShadowMap = t.SelfShadowMap;
                            m.Shadow        = t.Shadow;
                            m.Tex           = t.Tex;
                            m.EdgeSize      = t.EdgeSize;
                            m.EdgeColor     = t.EdgeColor;
                            m.Edge          = t.Edge;
                        }
                        break;

                    // Material library, may occur multiple times in a model.
                    case "mtllib":
                        string materialLibraryName = line.Substring(7);
                        progress.Report("Importing materials from " + materialLibraryName);
                        // Try relative path
                        string materialLibraryPath = Path.Combine(Path.GetDirectoryName(path), materialLibraryName);
                        if (!File.Exists(materialLibraryPath))
                        {
                            // Try absolute path
                            materialLibraryPath = materialLibraryName;
                            if (!File.Exists(materialLibraryPath))
                            {
                                progress.ReportError(string.Format("Material library not found ({0}).", materialLibraryName));
                                break;
                            }
                        }
                        Dictionary <string, IPXMaterial> tempDict = ImportMaterials(materialLibraryPath, builder, settings, progress);
                        foreach (KeyValuePair <string, IPXMaterial> kvp in tempDict)
                        {
                            if (materials.ContainsKey(kvp.Key))
                            {
                                progress.ReportWarning(string.Format("Duplicate material {0} imported from {1} has been discarded.", kvp.Key, materialLibraryName));
                            }
                            else
                            {
                                materials.Add(kvp.Key, kvp.Value);
                            }
                        }
                        progress.Report(string.Format("Imported {0} materials from {1}.", tempDict.Count, materialLibraryName));
                        break;

                    // Smoothing group assignment (unused)
                    case "s":
                        break;

                    default:
                        break;
                    }
                }

                // Second pass for bone weights and transformations because I'm lazy
                IPXBone bone = null;
                if (settings.CreateBone != ImportSettings.CreateBoneMode.None)
                {
                    bone      = builder.Bone();
                    bone.Name = bone.NameE = pmx.ModelInfo.ModelName.Replace(' ', '_');
                }
                foreach (IPXVertex vertex in pmx.Vertex)
                {
                    // Bone
                    if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                    {
                        bone.Position += vertex.Position;
                    }
                    vertex.Bone1   = settings.CreateBone != ImportSettings.CreateBoneMode.None ? bone : null;
                    vertex.Weight1 = 1.0f;
                    vertex.Bone2   = vertex.Bone3 = vertex.Bone4 = null;
                    vertex.Weight2 = vertex.Weight3 = vertex.Weight4 = 0;

                    // Axis swap
                    if (settings.SwapYZ)
                    {
                        float temp = vertex.Position.Y;
                        vertex.Position.Y = vertex.Position.Z;
                        vertex.Position.Z = temp;
                        temp            = vertex.Normal.Y;
                        vertex.Normal.Y = vertex.Normal.Z;
                        vertex.Normal.Z = temp;
                    }
                }
                if (settings.CreateBone == ImportSettings.CreateBoneMode.Average)
                {
                    bone.Position /= pmx.Vertex.Count;
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if (progress.ReportError(ex.ToString()))
                {
                    return(ImportResult.Fail(ex, progress.WarningCount, progress.ErrorCount));
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }

            return(ImportResult.Success(pmx, progress.WarningCount, progress.ErrorCount));
        }
Пример #12
0
        //DoWorkイベントハンドラ
        private void ProgressDialog_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = (BackgroundWorker)sender;

            bw.ReportProgress(0, "ファイル読み込み中(バーは動きません (^-^;)");
            using (FileFormat.MQOFile mqo = FileFormat.MQOFile.load(mqopath, true)) // 三角面化して読み込む
            {
                if (mqo == null)
                {
                    throw new Exception("読み込み失敗。おそらくmqoファイルの構文エラー。");
                }

                if (mqo.Object.Count == 0)
                {
                    throw new Exception("オブジェクトが空です。");
                }

                // pmx作成
                bld = PEStaticBuilder.Pmx;
                pmx = bld.Pmx();
                pmx.Clear();

                // モデル名は最初のオブジェクト名を利用する
                pmx.ModelInfo.ModelName = mqo.Object[0].Name;

                // 材質
                int mc = mqo.Material.Count;
                if (mc == 0)
                {
                    throw new Exception("材質がありません。少なくとも1つ材質が必要です。");
                }

                int cw = 100 / mc;
                int pc = 0;
                mqo.Material.ForEach(m =>
                {
                    bw.ReportProgress(cw * pc++, "材質の変換中");
                    IPXMaterial pm = bld.Material();
                    pm.Name        = m.Name;
                    pm.Diffuse.R   = (float)(m.Color.R * m.Diffuse);
                    pm.Diffuse.G   = (float)(m.Color.G * m.Diffuse);
                    pm.Diffuse.B   = (float)(m.Color.B * m.Diffuse);
                    pm.Diffuse.A   = (float)m.Color.A;
                    pm.Ambient.R   = (float)(m.Color.R * m.Ambient);
                    pm.Ambient.G   = (float)(m.Color.G * m.Ambient);
                    pm.Ambient.B   = (float)(m.Color.B * m.Ambient);
                    pm.Specular.R  = (float)(m.Color.R * m.Specular);
                    pm.Specular.G  = (float)(m.Color.G * m.Specular);
                    pm.Specular.B  = (float)(m.Color.B * m.Specular);
                    pm.Power       = (float)m.Power;
                    pm.Tex         = m.Tex;
                    pmx.Material.Add(pm);
                });

                // 各オブジェクトを処理
                // ただし、非表示オブジェクトはスキップ
                mc = mqo.Object.Count;
                cw = 100 / mc;
                bw.ReportProgress(0, "法線を計算中");
                Parallel.ForEach(mqo.Object, mObj =>
                {
                    if (mObj.Visible)
                    {
                        mObj.CalcNormals();
                    }
                    bw.ReportProgress(cw, 1);
                });

                // 先に頂点をすべて登録してから面を登録する
                // 頂点登録と面登録を交互に行うととんでもなく遅くなる
                mc = mqo.Material.Count;
                WorkFaceList   workfacelist   = new WorkFaceList(mc);
                WorkVertexDict workvertexdict = new WorkVertexDict();

                mc = mqo.Object.Count;
                cw = 100 / mc;
                pc = 0;
                for (int objID = 0; objID < mc; objID++)
                {
                    var mObj = mqo.Object[objID];
                    bw.ReportProgress(cw * pc++, String.Format("'{0}'の変換中", mObj.Name));
                    mObj.Face.ForEach(fc =>
                    {
                        if (!mObj.Visible)
                        {
                            return;                // 非表示オブジェクトは無視
                        }
                        // 材質割り当てのない面は材質0として処理
                        int matID = fc.MatID < 0 ? 0 : fc.MatID;

                        Func <int, int> get_vertex = i => workvertexdict.RegistVertex(objID, fc.VertexID[i], fc.UVID[i], fc.NormalID[i]);
                        workfacelist.AddFace(matID, get_vertex(0), get_vertex(1), get_vertex(2));
                    });
                }

                workvertexdict.RegistToPmx(pmx, bld, mqo, bw);
                workfacelist.RegistToPmx(pmx, bld, mqo, workvertexdict, bw);
            }
        }