Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    [FWD] How to retrieve the index of the closest polygon in a mesh to a point?

    Cinema 4D SDK
    c++ r23 windows macos
    1
    2
    351
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ferdinandF
      ferdinand
      last edited by

      Dear community,

      we received a support request via mail which we thought might also be interesting to the community. This thread captures the question asked in the mail.

      The question is "How to retrieve the index of the closest polygon in a mesh to a point?". The question has been asked for the C++ environment, looking for the right optimization data structure provided by the C++ SDK.

      Cheers,
      Ferdinand

      MAXON SDK Specialist
      developers.maxon.net

      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by ferdinand

        Dear user,

        the problem with your example code is that you do use a VoxelizationInterface which is not well suited for this task. The type DistanceQueryInterface(Documentation) is much better suited for the task. You should also be more cautious with statements like the following, taken from your code,

        voxelRef = maxon::PolyVoxelization().Create() iferr_ignore("Could not create VoxelizationRef");
        

        as stepping over a failure of initialization will lead to crashes. At the end of this posting you will find an example for how to use DistanceQueryInterface as well as some light comments on error handling.

        I hope this helps and cheers,
        Ferdinand

        /* This function expects a point object (A) to be the first object in the scene, followed by a 
           polygon object (B) as the second object. It will then return the index for closest polygon
           in B for each vertex in A.
        */
        static maxon::Result<void> Pc13296(BaseDocument* doc)
        {
        	iferr_scope;
        
        	// Get the first and second node in the scene. The first one is expected
        	// to be a point node, serving as a point source, and the second one is
        	// expected to be a polygon node, serving as a polygon source.
        	BaseObject* node = doc->GetFirstObject();
        	if (node == nullptr || !node->IsInstanceOf(Opoint))
        	{
        		ApplicationOutput("Please provide a point object as the first node in the scene."_s);
        		return maxon::OK;
        	}
        	PointObject* pointNode = static_cast<PointObject*>(node);
        
        	node = node->GetNext();
        	if (node == nullptr || !node->IsInstanceOf(Opolygon))
        	{
        		ApplicationOutput("Please provide a polygon object as the second node in the scene."_s);
        		return maxon::OK;
        	}
        	PolygonObject* polygonNode = static_cast<PolygonObject*> (node);
        
        	// Get access to the point and polygon data and the global transforms of both nodes.
        	const Vector* points = pointNode->GetPointR();
        	const CPolygon* polygons = polygonNode->GetPolygonR();
        	const int pointCount = pointNode->GetPointCount();
        	const int polygonCount = polygonNode->GetPolygonCount();
        	Matrix mgPointNode = pointNode->GetMg();
        	// We invert it right away, as we only will need it in this form.
        	Matrix iMgPolygonNode = ~polygonNode->GetMg();
        
        	// When an error is being raised by Cinema we should be cautious with using iferr_ingore, as
        	// then the code will keep running in the current scope. In some cases like manipulating an 
        	// array like structure this can be useful. But when an initialization of an entity fails, we
        	// almost never want to keep going, as trying to use that not initialized object then will be
        	// a sure fire way to crash Cinema 4D. Instead we can either use iferr_return to simply leave 
        	// the current scope, use iferr_throw to throw a specific error or handle it manually with
        	// iferr(). Below you will find a two examples.
        
        	// Create a reference to the distance query interface.
        	maxon::DistanceQueryRef distanceQuery = maxon::DistanceCalculator().Create() iferr_return;
        
        	// Pass true for the second argument to voxelize the input to speed up larger queries. Just as
        	// with any optimization, for smaller data sets this voxelization setup might eat up all the
        	// performance benefits gained latter on.
        	iferr(distanceQuery.Init(polygonNode, false)) {
        		ApplicationOutput("Failed to initialize DistanceQueryInterfacae for @", polygonNode->GetName());
        		return maxon::OK;
        	}
        
        	// Go over all vertices and query them for the closest polygon (id) in the other mesh.
        	float distance = 0;
        	Vector p;
        	for (int poindId = 0; poindId < pointCount; poindId++)
        	{
        		// The point in the point mesh converted first to global coordinates and then to local
        		// coordinates in the polygon node. We have to do that because the points in the point
        		// source live in their own coordinate system as well the ones in the polygon source.
        		p = mgPointNode * iMgPolygonNode * points[poindId];
        		maxon::PrimitiveInformation info;
        		distance = distanceQuery.GetClosestMeshPrimitive(p, info);
        		ApplicationOutput("Closest polygon id for point id @: @", poindId, info.GetRealPolyIndex());
        	}
        
        	return maxon::OK;
        }
        

        The output/setup:
        642545d3-3ffa-467e-9123-cf0a328b18f1-image.png

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • First post
          Last post