UV Count is different with Vertex Count

As I understand “Mesh.ControlPoints” is represent mesh’s vertex.
Also “VertexElementUV.Data” represent mesh’s UV value for each vertex.
then I think those count always same but UV count is different with mesh vertex count many cases.

which way is best way to get each mesh’s vertex position, and corresponding UV values?

        foreach (var entity in node.Entities)
        {
            switch (entity)
            {
                case Mesh mesh:
                    var vertices = new List<UnityEngine.Vector3>();
                    var triangles = new List<int>();
                    var polygons = mesh.Polygons;
                    var controlPoints = mesh.ControlPoints;
                    var triangleFaces = PolygonModifier.Triangulate(controlPoints, mesh.Polygons);
                    var transform = node.GlobalTransform.TransformMatrix;
                    var pointCount = controlPoints.Count;
                    for (var i = 0; i < pointCount; i++)
                    {
                        var vertex = controlPoints[i];
                        vertices.Add(new Vector3((float)vertex.x, (float)vertex.y, (float)vertex.z));
                    }
                    var triangleCount = triangleFaces.Length;
                    for (var i = 0; i < triangleCount; i++)
                    {
                        triangles.Add(triangleFaces[i][0]);
                        triangles.Add(triangleFaces[i][1]);
                        triangles.Add(triangleFaces[i][2]);
                    }
                    var normals = new List<Vector3>();
                    var uvs = new List<Vector2>();
                    foreach (var vertexElement in mesh.VertexElements)
                    {
                        var elementType = vertexElement.VertexElementType;
                        switch (elementType)
                        {
                            case VertexElementType.Binormal:
                                break;
                            case VertexElementType.Normal:
                                {
                                    var vertexElementNormal = vertexElement as VertexElementNormal;
                                    normals = vertexElementNormal.Data
                                                              .Select(v =>
                                                                  new Vector3((float) v.x, (float) v.y, (float) v.z))
                                                              .ToList();
                                    break;
                                }
                            case VertexElementType.Tangent:
                                break;
                            case VertexElementType.Material:
                            {
                                var vertexElementMaterial = vertexElement as VertexElementMaterial;
                                break;
                                }
                            case VertexElementType.PolygonGroup:
                                break;
                            case VertexElementType.UV:
                                {
                                    var vertexElementUV = vertexElement as VertexElementUV;
                                    uvs = vertexElementUV.Data.Select(v => new Vector2((float) v.x, (float) v.y))
                                                         .ToList();
                                    break;
                                }
                            case VertexElementType.VertexColor:
                                break;
                            case VertexElementType.SmoothingGroup:
                                break;
                            case VertexElementType.VertexCrease:
                                break;
                            case VertexElementType.EdgeCrease:
                                break;
                            case VertexElementType.UserData:
                                break;
                            case VertexElementType.Visibility:
                                break;
                            case VertexElementType.Specular:
                                break;
                            case VertexElementType.Weight:
                                break;
                            case VertexElementType.Hole:
                                break;
                            default:
                                break;
                        }
                    }

                    // TODO: some of cases are not equal uv count and vertex count
                    var uvDataList = new List<Vector2[]>(){ uvs.ToArray() };
                    if (uvs.Count != vertices.Count)
                    {
                        uvDataList = null;
                    }

                    var meshData = new MeshData(vertices.ToArray(), triangles.ToArray(), uvDataList, texturePacks.Count > 0 ? texturePacks: null,
                        null, normals.ToArray(), null);
                    meshes.Add(meshData);

                    break;
                default:
                    break;
            }
        }

@HuePark

Would you please also share the sample source file with us so that we can test the scenario in our environment and address it accordingly.

Question is basically UV count and Vertex count should same?
then what is best way to get vertices and uvs?

@HuePark

They are not the same, because Mesh in Aspose.3D is not a Triangle-based mesh, but a more powerful implementation. The VertexElement will reuse data by MappingMode/ReferenceMode, so UV count can be different to the Vertex count.

Below is a sample code to manually calculate the data from reused vertex element instance:

/// <summary>
/// Get the vertex element data for specified vertex
/// </summary>
/// <param name="ve">Vertex element</param>
/// <param name="controlPointId">Control point index</param>
/// <param name="edgeId">Control point index</param>
/// <param name="polygonId">Polygon index</param>
/// <param name="vertexId">Polygon vertex index</param>
/// <returns></returns>
public T SelectData<T>(VertexElementTemplate<T> ve, int controlPointId, int edgeId, int polygonId, int vertexId)
{
int id = 0;
switch(ve.MappingMode)
{
case MappingMode.AllSame:
//the data is all same for all control points/polygon/vertex
return ve.Data[0];
case MappingMode.ControlPoint:
//the data is mapped by control point
id = controlPointId;
break;
case MappingMode.Polygon:
//the data is mapped by polygon
id = polygonId;
break;
case MappingMode.PolygonVertex:
//the data is mapped by polygon's vertex
id = vertexId;
break;
case MappingMode.Edge:
//the data is mapped by edge.
id = edgeId;
break;
}
if (ve.ReferenceMode == ReferenceMode.IndexToDirect)
id = ve.Indices[id];
return ve.Data[id];
}

Furthermore, it seems that you are trying to construct the triangles from the Mesh instance. You can do it in a better way using this example.

Thank you for your answer.

is TriMesh triangle-based mesh?
I just found TriMesh.FromMesh(Mesh) function for convert to triangle-based mesh.
but I couldn’t find example of how to access each data.
Can you explain little more?

what I want to get from triangle-based mesh

  1. each vertex (x, y, z)
  2. each uv
  3. triangle indices(int[])

@HuePark

Yes, the TriMesh is GPU friendly triangle-based mesh. You can find further code samples in the Aspose.3D for .NET 20.4 release notes.