Get a vertex raw index of a ON_Mesh which import from a .obj mesh file

Hi,
I’m working at a surface unroll plugin.
By SampleTriangleMesh , I can import a wavefront .obj file and get corresponding ON_Mesh object.

I wonder if I can get this ON_Mesh objects’ raw vertex index(means the line number of vertices coordinates in .obj file) by CRhinoGetObject?

Currently I try to use code below to get raw vertex indices:

    CRhGetMeshComponentRef gv(mesh_object->RuntimeSerialNumber());
	gv.SetCommandPrompt(L"Select mesh vertex");
	gv.SetGeometryFilter(CRhinoGetObject::meshvertex_filter);
	gv.GetObjects(1, 0);
	if (gv.CommandResult() != CRhinoCommand::success)
		return ;

	for (int i = 0; i < gv.ObjectCount(); i++) {
		const ON_MeshComponentRef* mesh_vertex_ref = gv.Object(i).MeshComponentRef();
		if (nullptr == mesh_vertex_ref) {
			RhinoApp().Print(L"Selected vertex INVALID!");
			return;
		}

		ON_3dPoint position;
		const ON_MeshTopologyVertex* tempTopVertex;
		unsigned int tIndex = mesh_vertex_ref->GetMeshTopologyVertexAndPoint(tempTopVertex, position);
		int index = tempTopVertex->m_vi[0];
		RhinoApp().Print(L"Selected mesh vertex[%d] index = %d, tIndex = %d, location:[ %d, %d, %d ]\n", i, index, tIndex, position.x, position.y, position.z);

		ON_wString wstr;
		wstr.Format(L"%d", i);
		ON_TextDot dot(position, wstr, 0);
		CRhinoTextDot* obj = new CRhinoTextDot();
		obj->SetDot(dot);

		RhinoApp().ActiveDoc()->AddObject(obj);
    }

I tried to pick the cathead.obj (7.1 KB) boundary loop in clockwise.
Compared to some 3rdparty geometry processing library, OpenNurbs return different boundary Indices:

Selected mesh vertex[0] index = 419, tIndex = 85, location:[ -1152563064, -1445582913, -1318589320 ]
Selected mesh vertex[1] index = 442, tIndex = 89, location:[ 471415610, 1473620459, -2113261349 ]
Selected mesh vertex[2] index = 624, tIndex = 119, location:[ 1019247279, 142111878, 1137444779 ]
Selected mesh vertex[3] index = 631, tIndex = 120, location:[ 1726233256, 1475819482, 936783907 ]
Selected mesh vertex[4] index = 688, tIndex = 127, location:[ -1841132221, -1320788343, -1441184866 ]
Selected mesh vertex[5] index = 701, tIndex = 129, location:[ -1335906628, -189940634, 595385546 ]
Selected mesh vertex[6] index = 662, tIndex = 125, location:[ 0, -1477578701, -1985443122 ]
Selected mesh vertex[7] index = 622, tIndex = 118, location:[ 1497534837, 803468122, -360090058 ]
Selected mesh vertex[8] index = 603, tIndex = 113, location:[ -613527488, -1948609482, 1642670372 ]
Selected mesh vertex[9] index = 503, tIndex = 99, location:[ -2001770870, -1441184866, 2059110401 ]
Selected mesh vertex[10] index = 500, tIndex = 97, location:[ -1695996686, 8796093, -1985443122 ]
Selected mesh vertex[11] index = 434, tIndex = 88, location:[ 1436786820, -1477578701, -274328151 ]
ON_TextDot number OpenNurbs libigl other…
0 85 85 85
1 89 89 89
2 119 119 119
3 120 120 120
4 127 127 127
5 129 129 129
6 125 125 125
7 118 118 118
8 113 113 113
9 99 98 98
10 97 97 97
11 88 88 88

:point_up: can you share the code for this too, it is difficult to reproduce without.

sure, @menno

I have done nothing but just copy it from github.


//https://github.com/mcneel/rhino-developer-samples/blob/6/cpp/SampleCommands/cmdSampleMeshFacePicker.cpp
class CRhGetMeshComponentRef : public CRhinoGetObject
{
public:
	CRhGetMeshComponentRef(unsigned int runtime_object_serial_number)
		: m_runtime_object_serial_number(runtime_object_serial_number) {}

	//CRhinoGetObject override
	bool CustomGeometryFilter(const CRhinoObject* object, const ON_Geometry* geometry, ON_COMPONENT_INDEX component_index) const {
		UNREFERENCED_PARAMETER(geometry);
		UNREFERENCED_PARAMETER(component_index);
		return (nullptr != object && object->RuntimeSerialNumber() == m_runtime_object_serial_number);
	}

private:
	unsigned int m_runtime_object_serial_number;
};
1 Like

Which version of Rhino are you using? The numbers you get for index should all be in the range [0…131] so that is a bit strange. When I try to reproduce what you see, I get this (all index == tIndex and ,as expected, 98, not 99)

Selected mesh vertex[0] index = 85, tIndex = 85, location:[ -1152563064, -1445582913, -1318589320 ]
Selected mesh vertex[1] index = 89, tIndex = 89, location:[ 471415610, 1473620459, -2113261349 ]
Selected mesh vertex[2] index = 119, tIndex = 119, location:[ 1019247279, 142111878, 1137444779 ]
Selected mesh vertex[3] index = 120, tIndex = 120, location:[ 1726233256, 1475819482, 936783907 ]
Selected mesh vertex[4] index = 127, tIndex = 127, location:[ -1841132221, -1320788343, -1441184866 ]
Selected mesh vertex[5] index = 129, tIndex = 129, location:[ -1335906628, -189940634, 595385546 ]
Selected mesh vertex[6] index = 125, tIndex = 125, location:[ 0, -1477578701, -1985443122 ]
Selected mesh vertex[7] index = 118, tIndex = 118, location:[ 1497534837, 803468122, -360090058 ]
Selected mesh vertex[8] index = 113, tIndex = 113, location:[ -613527488, -1948609482, 1642670372 ]
--> Selected mesh vertex[9] index = 98, tIndex = 98, location:[ -2001770870, -1441184866, 2059110401 ]
Selected mesh vertex[10] index = 97, tIndex = 97, location:[ -1695996686, 8796093, -1985443122 ]
Selected mesh vertex[11] index = 88, tIndex = 88, location:[ 1436786820, -1477578701, -274328151 ]

Thank you for your reply, @menno
I was developing at Rhino 6 now.
Rhino version: Rhino_6.29.20238
SDK version: rh629sdk_6.2920238.11501

I see. All I can say is, it is working as expected in Rhino 8.
And again, the values for index are suspect, that’s what I’d look at first.

Thanks, @menno
Those indices looks no problem now after I changed the code from SampleTriangleMesh

origin

ON_Mesh* CreateMeshFromTriangles(const ON_SimpleArray<CTriangle>& triangles)
{
  const int triangle_count = triangles.Count();
  if (0 == triangle_count)
    return nullptr;

  ON_Mesh* mesh = new ON_Mesh(triangle_count, triangle_count * 3, true, false);

  int vi = 0, fi = 0;
  for (int i = 0; i < triangle_count; i++)
  {
    for (int j = 0; j < 3; j++)
      mesh->SetVertex(vi++, triangles[i][j]);
    mesh->SetTriangle(fi++, vi - 3, vi - 2, vi - 1);
  }

  mesh->ComputeVertexNormals();
  mesh->Compact();

  if (!mesh->IsValid())
  {
    delete mesh;
    mesh = nullptr;
  }

  return mesh;
}

new

ON_Mesh* CreateMeshFromTriangles(const Eigen::MatrixXd& vertices, const Eigen::MatrixXi& faceConnectivity)
	{
		int vNum = vertices.rows();
		int fNum = faceConnectivity.rows();

		if (0 == vNum)
			return nullptr;

		ON_Mesh* mesh = new ON_Mesh(fNum, vNum, false, false);
		for (int i = 0; i < vNum; ++i) {
			ON_3dPoint point(vertices.row(i).x(), vertices.row(i).y(), vertices.row(i).z());
			mesh->SetVertex(i, point);
		}

		for (int i = 0; i < fNum; ++i) {
			mesh->SetTriangle(i, faceConnectivity.row(i).x(), faceConnectivity.row(i).y(), faceConnectivity.row(i).z());
		}

		mesh->Compact();

		if (!mesh->IsValid())
		{
			delete mesh;
			mesh = nullptr;
		}

		return mesh;
	}
1 Like