Hello @indexofrefraction,
as a disclaimer upfront, this is a private posting of mine, your case is still being handled by @m_adam.
When I see your case correctly, you are interested in the point p and its normal n on a polygonal mesh M that is closest to a given point q on a spline S. Or in short, you are interested in the projection of q onto M. Ray-casting, e.g., GeRayCollider
, will not help you much here I would say, since coming up with a ray-casting direction is the same problem as the one you are trying to solve; as you already did find out yourself.
Cinema 4D's Python SDK has no projection helper class, so, you would have to do that on your own. The general procedure would be:
- Find the the vertex v in M that is closest to q.
- Get the list L of all polygons that are attached to v - you can use
c4d.utils.Neighbor
for that.
- Project q onto all polygons in L and store the results in R. Principally, what one has to do here is point-plane projections. The concrete procedure is something like the following for a single polygon P.
a. Compute the point-plane projection proj of q for each triangle T in P.
b. Convert proj from Cartesian into Barycentric coordinates and clamp the point to the interval [0, 1]. We have to do this since there is no guarantee that the point we projected onto the plane of T actually does lie within T. So, we ware using Barycentric coordinates to rectify this.
c. Convert the clamped points back into Cartesian coordinates and then select the one closest to q. This point is the clamped projection of q onto P.
- Select the point in R that is closest to q, that point is p, the projection of your query point q onto M.
- Define the normal of p as one of the normals of the polygon P the point p is associated with. That polygon is already known to us due to the prior computations. How to compute the normal exactly depends on what you would consider to be the object normal.
For all that you do not need any fancy classes or libraries, but it can be a bit slow if you do this for very large meshes. The expensive part is the first step, finding the closest vertex v in M. Which is probably why Maxime mentioned kd-trees. They are a form Binary-Space-Partitioning, i.e., a performant way to find the closest point p out of a point cloud C for a query point q. Since the Cinema Python SDK has no kd-Tree, you would have to write your own BSP implementation, a octree would be enough in this case (which is effectively just a clever form of a 3D-lattice). But this is not really needed functionality-wise, it will just make your solution more performant.
Cheers,
Ferdinand