/// <summary>
        /// Extract geometry (position, normal, UVs...) for a specific vertex
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="polygonId">The polygon (face) to examine</param>
        /// <param name="vertexIndexGlobal">The object-relative (mesh-relative/global) vertex index</param>
        /// <param name="vertexIndexLocal">The face-relative (local) vertex id to examine</param>
        /// <param name="hasUV"></param>
        /// <returns></returns>
        private GlobalVertex ExtractVertex(MFnMesh mFnMesh, int polygonId, int vertexIndexGlobal, int vertexIndexLocal, bool hasUV)
        {
            MPoint point = new MPoint();

            mFnMesh.getPoint(vertexIndexGlobal, point);

            MVector normal = new MVector();

            mFnMesh.getFaceVertexNormal(polygonId, vertexIndexGlobal, normal);

            // Switch coordinate system at object level
            point.z  *= -1;
            normal.z *= -1;

            var vertex = new GlobalVertex
            {
                BaseIndex = vertexIndexGlobal,
                Position  = point.toArray(),
                Normal    = normal.toArray()
            };

            // UV
            if (hasUV)
            {
                float u = 0, v = 0;
                mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v);
                vertex.UV = new float[] { u, v };
            }

            return(vertex);
        }
        /// <summary>
        /// Extract ordered indices on a triangle basis
        /// Extract position and normal of each vertex per face
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        /// <param name="subMeshes"></param>
        /// <param name="optimizeVertices"></param>
        private void ExtractGeometry(MFnMesh mFnMesh, List <GlobalVertex> vertices, List <int> indices, List <BabylonSubMesh> subMeshes, bool optimizeVertices)
        {
            // TODO - Multimaterials: create a BabylonSubMesh per submaterial
            // TODO - optimizeVertices
            MIntArray triangleCounts    = new MIntArray();
            MIntArray trianglesVertices = new MIntArray();

            mFnMesh.getTriangles(triangleCounts, trianglesVertices);

            // For each polygon of this mesh
            for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++)
            {
                MIntArray verticesId  = new MIntArray();
                int       nbTriangles = triangleCounts[polygonId];

                // For each triangle of this polygon
                for (int triangleIndex = 0; triangleIndex < triangleCounts[polygonId]; triangleIndex++)
                {
                    int[] triangleVertices = new int[3];
                    mFnMesh.getPolygonTriangleVertices(polygonId, triangleIndex, triangleVertices);

                    // Inverse winding order
                    var tmp = triangleVertices[1];
                    triangleVertices[1] = triangleVertices[2];
                    triangleVertices[2] = tmp;

                    // For each vertex of this triangle (3 vertices per triangle)
                    foreach (int vertexId in triangleVertices)
                    {
                        MPoint point = new MPoint();
                        mFnMesh.getPoint(vertexId, point);

                        MVector normal = new MVector();
                        mFnMesh.getFaceVertexNormal(polygonId, vertexId, normal);

                        var vertex = new GlobalVertex
                        {
                            BaseIndex = vertexId,
                            Position  = point.toArray(),
                            Normal    = normal.toArray()
                        };

                        indices.Add(vertices.Count);
                        vertices.Add(vertex);
                    }
                }
            }

            // BabylonSubMesh
            var subMesh = new BabylonSubMesh {
                indexStart = 0, materialIndex = 0
            };

            subMeshes.Add(subMesh);

            subMesh.indexCount    = indices.Count;
            subMesh.verticesStart = 0;
            subMesh.verticesCount = vertices.Count;
        }
Exemple #3
0
        /// <summary>
        /// Extract geometry (position, normal, UVs...) for a specific vertex
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="polygonId">The polygon (face) to examine</param>
        /// <param name="vertexIndexGlobal">The object-relative (mesh-relative/global) vertex index</param>
        /// <param name="vertexIndexLocal">The face-relative (local) vertex id to examine</param>
        /// <param name="uvSetNames"></param>
        /// <param name="isUVExportSuccess"></param>
        /// <returns></returns>
        private GlobalVertex ExtractVertex(MFnMesh mFnMesh, int polygonId, int vertexIndexGlobal, int vertexIndexLocal, MStringArray uvSetNames, ref bool[] isUVExportSuccess)
        {
            MPoint point = new MPoint();

            mFnMesh.getPoint(vertexIndexGlobal, point);

            MVector normal = new MVector();

            mFnMesh.getFaceVertexNormal(polygonId, vertexIndexGlobal, normal);

            // Switch coordinate system at object level
            point.z  *= -1;
            normal.z *= -1;

            var vertex = new GlobalVertex
            {
                BaseIndex = vertexIndexGlobal,
                Position  = point.toArray(),
                Normal    = normal.toArray(),
            };

            // TODO - Export colors ?
            //// Color
            //int colorIndex;
            //string colorSetName;
            //float[] defaultColor = new float[] { 0.5f, 0.5f, 0.5f, 1 };
            //MColor color = new MColor();
            //mFnMesh.getCurrentColorSetName(out colorSetName);

            //if (mFnMesh.numColors(colorSetName) > 0)
            //{
            //    //Get the color index
            //    mFnMesh.getColorIndex(polygonId, vertexIndexLocal, out colorIndex);

            //    //if a color is set
            //    if (colorIndex != -1)
            //    {
            //        mFnMesh.getColor(colorIndex, color);
            //        vertex.Color = color.toArray();
            //    }
            //    //else set the color to the default one of Maya
            //    else
            //    {
            //        vertex.Color = defaultColor;
            //    }
            //}
            //else
            //{
            //    vertex.Color = defaultColor;
            //}

            // UV
            int indexUVSet = 0;

            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV = new float[] { u, v };
                }
                catch (Exception e)
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }
            indexUVSet = 1;
            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV2 = new float[] { u, v };
                }
                catch (Exception e)
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }


            return(vertex);
        }
Exemple #4
0
        /// <summary>
        /// Extract geometry (position, normal, UVs...) for a specific vertex
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="polygonId">The polygon (face) to examine</param>
        /// <param name="vertexIndexGlobal">The object-relative (mesh-relative/global) vertex index</param>
        /// <param name="vertexIndexLocal">The face-relative (local) vertex id to examine</param>
        /// <param name="uvSetNames"></param>
        /// <param name="isUVExportSuccess"></param>
        /// <returns></returns>
        private GlobalVertex ExtractVertex(MFnMesh mFnMesh, int polygonId, int vertexIndexGlobal, int vertexIndexLocal, MStringArray uvSetNames, ref bool[] isUVExportSuccess, ref bool isTangentExportSuccess)
        {
            MPoint point = new MPoint();

            mFnMesh.getPoint(vertexIndexGlobal, point);

            MVector normal = new MVector();

            mFnMesh.getFaceVertexNormal(polygonId, vertexIndexGlobal, normal);

            // Switch coordinate system at object level
            point.z  *= -1;
            normal.z *= -1;

            var vertex = new GlobalVertex
            {
                BaseIndex = vertexIndexGlobal,
                Position  = point.toArray(),
                Normal    = normal.toArray()
            };

            // Tangent
            if (isTangentExportSuccess)
            {
                try
                {
                    MVector tangent = new MVector();
                    mFnMesh.getFaceVertexTangent(polygonId, vertexIndexGlobal, tangent);

                    // Switch coordinate system at object level
                    tangent.z *= -1;

                    int  tangentId            = mFnMesh.getTangentId(polygonId, vertexIndexGlobal);
                    bool isRightHandedTangent = mFnMesh.isRightHandedTangent(tangentId);

                    // Invert W to switch to left handed system
                    vertex.Tangent = new float[] { (float)tangent.x, (float)tangent.y, (float)tangent.z, isRightHandedTangent ? -1 : 1 };
                }
                catch
                {
                    // Exception raised when mesh don't have tangents
                    isTangentExportSuccess = false;
                }
            }

            // Color
            int    colorIndex;
            string colorSetName;

            float[] defaultColor = new float[] { 1, 1, 1, 0 };
            MColor  color        = new MColor();

            mFnMesh.getCurrentColorSetName(out colorSetName);

            if (mFnMesh.numColors(colorSetName) > 0)
            {
                //Get the color index
                mFnMesh.getColorIndex(polygonId, vertexIndexLocal, out colorIndex);

                //if a color is set
                if (colorIndex != -1)
                {
                    mFnMesh.getColor(colorIndex, color);
                    vertex.Color = color.toArray();
                }
                //else set the default color
                else
                {
                    vertex.Color = defaultColor;
                }
            }

            // UV
            int indexUVSet = 0;

            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV = new float[] { u, v };
                }
                catch
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }
            indexUVSet = 1;
            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV2 = new float[] { u, v };
                }
                catch
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }

            // skin
            if (mFnSkinCluster != null)
            {
                // Filter null weights
                Dictionary <int, double> weightByInfluenceIndex = new Dictionary <int, double>(); // contains the influence indices with weight > 0

                // Export Weights and BonesIndices for the vertex
                // Get the weight values of all the influences for this vertex
                allMayaInfluenceWeights = new MDoubleArray();
                MGlobal.executeCommand($"skinPercent -query -value {mFnSkinCluster.name} {mFnTransform.name}.vtx[{vertexIndexGlobal}]",
                                       allMayaInfluenceWeights);
                allMayaInfluenceWeights.get(out double[] allInfluenceWeights);

                for (int influenceIndex = 0; influenceIndex < allInfluenceWeights.Length; influenceIndex++)
                {
                    double weight = allInfluenceWeights[influenceIndex];

                    if (weight > 0)
                    {
                        try
                        {
                            // add indice and weight in the local lists
                            weightByInfluenceIndex.Add(indexByNodeName[allMayaInfluenceNames[influenceIndex]], weight);
                        }
                        catch (Exception e)
                        {
                            RaiseError(e.Message, 2);
                            RaiseError(e.StackTrace, 3);
                        }
                    }
                }

                // normalize weights => Sum weights == 1
                Normalize(ref weightByInfluenceIndex);

                // decreasing sort
                OrderByDescending(ref weightByInfluenceIndex);

                int   bonesCount = indexByNodeName.Count; // number total of bones/influences for the mesh
                float weight0    = 0;
                float weight1    = 0;
                float weight2    = 0;
                float weight3    = 0;
                int   bone0      = bonesCount;
                int   bone1      = bonesCount;
                int   bone2      = bonesCount;
                int   bone3      = bonesCount;
                int   nbBones    = weightByInfluenceIndex.Count; // number of bones/influences for this vertex

                if (nbBones == 0)
                {
                    weight0 = 1.0f;
                    bone0   = bonesCount;
                }

                if (nbBones > 0)
                {
                    bone0   = weightByInfluenceIndex.ElementAt(0).Key;
                    weight0 = (float)weightByInfluenceIndex.ElementAt(0).Value;

                    if (nbBones > 1)
                    {
                        bone1   = weightByInfluenceIndex.ElementAt(1).Key;
                        weight1 = (float)weightByInfluenceIndex.ElementAt(1).Value;

                        if (nbBones > 2)
                        {
                            bone2   = weightByInfluenceIndex.ElementAt(2).Key;
                            weight2 = (float)weightByInfluenceIndex.ElementAt(2).Value;

                            if (nbBones > 3)
                            {
                                bone3   = weightByInfluenceIndex.ElementAt(3).Key;
                                weight3 = (float)weightByInfluenceIndex.ElementAt(3).Value;
                            }
                        }
                    }
                }

                float[] weights = { weight0, weight1, weight2, weight3 };
                vertex.Weights      = weights;
                vertex.BonesIndices = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0;

                if (nbBones > 4)
                {
                    bone0   = weightByInfluenceIndex.ElementAt(4).Key;
                    weight0 = (float)weightByInfluenceIndex.ElementAt(4).Value;
                    weight1 = 0;
                    weight2 = 0;
                    weight3 = 0;

                    if (nbBones > 5)
                    {
                        bone1   = weightByInfluenceIndex.ElementAt(5).Key;
                        weight1 = (float)weightByInfluenceIndex.ElementAt(4).Value;

                        if (nbBones > 6)
                        {
                            bone2   = weightByInfluenceIndex.ElementAt(6).Key;
                            weight2 = (float)weightByInfluenceIndex.ElementAt(4).Value;

                            if (nbBones > 7)
                            {
                                bone3   = weightByInfluenceIndex.ElementAt(7).Key;
                                weight3 = (float)weightByInfluenceIndex.ElementAt(7).Value;
                            }
                        }
                    }

                    float[] weightsExtra = { weight0, weight1, weight2, weight3 };
                    vertex.WeightsExtra      = weightsExtra;
                    vertex.BonesIndicesExtra = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0;
                }
            }
            return(vertex);
        }
        /// <summary>
        /// Extract geometry (position, normal, UVs...) for a specific vertex
        /// </summary>
        /// <param name="mFnMesh"></param>
        /// <param name="polygonId">The polygon (face) to examine</param>
        /// <param name="vertexIndexGlobal">The object-relative (mesh-relative/global) vertex index</param>
        /// <param name="vertexIndexLocal">The face-relative (local) vertex id to examine</param>
        /// <param name="uvSetNames"></param>
        /// <param name="isUVExportSuccess"></param>
        /// <returns></returns>
        private GlobalVertex ExtractVertex(MFnMesh mFnMesh, int polygonId, int vertexIndexGlobal, int vertexIndexLocal, MStringArray uvSetNames, ref bool[] isUVExportSuccess)
        {
            MPoint point = new MPoint();

            mFnMesh.getPoint(vertexIndexGlobal, point);

            MVector normal = new MVector();

            mFnMesh.getFaceVertexNormal(polygonId, vertexIndexGlobal, normal);

            MVector tangent = new MVector();

            mFnMesh.getFaceVertexTangent(polygonId, vertexIndexGlobal, tangent);

            // Switch coordinate system at object level
            point.z   *= -1;
            normal.z  *= -1;
            tangent.z *= -1;

            float[] tangentVec4 = new float[] { (float)tangent.x, (float)tangent.y, (float)tangent.z, -1 };

            var vertex = new GlobalVertex
            {
                BaseIndex = vertexIndexGlobal,
                Position  = point.toArray(),
                Normal    = normal.toArray(),
                Tangent   = tangentVec4,
            };

            // Color
            int    colorIndex;
            string colorSetName;

            float[] defaultColor = new float[] { 1, 1, 1, 0 };
            MColor  color        = new MColor();

            mFnMesh.getCurrentColorSetName(out colorSetName);

            if (mFnMesh.numColors(colorSetName) > 0)
            {
                //Get the color index
                mFnMesh.getColorIndex(polygonId, vertexIndexLocal, out colorIndex);

                //if a color is set
                if (colorIndex != -1)
                {
                    mFnMesh.getColor(colorIndex, color);
                    vertex.Color = color.toArray();
                }
                //else set the default color
                else
                {
                    vertex.Color = defaultColor;
                }
            }

            // UV
            int indexUVSet = 0;

            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV = new float[] { u, v };
                }
                catch (Exception e)
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }
            indexUVSet = 1;
            if (uvSetNames.Count > indexUVSet && isUVExportSuccess[indexUVSet])
            {
                try
                {
                    float u = 0, v = 0;
                    mFnMesh.getPolygonUV(polygonId, vertexIndexLocal, ref u, ref v, uvSetNames[indexUVSet]);
                    vertex.UV2 = new float[] { u, v };
                }
                catch (Exception e)
                {
                    // An exception is raised when a vertex isn't mapped to an UV coordinate
                    isUVExportSuccess[indexUVSet] = false;
                }
            }

            return(vertex);
        }
Exemple #6
0
 public static string toString(this MPoint mPoint)
 {
     return(mPoint == null ? "" : mPoint.toArray().toString());
 }