2
$\begingroup$

How to use Python to set the tilt of a curve towards a target object? enter image description here

I wrote some code, but I encountered difficulties in setting the tilt and couldn't solve them. Please help me.

import bpy
import math


def find_closest_vertex(obj, target_vertex):
    vertices = obj.data.vertices

    min_distance = float("inf")
    closest_vertex = None

    for vertex in vertices:
        distance = math.sqrt((vertex.co[0] - target_vertex[0]) ** 2 + (vertex.co[1] - target_vertex[1]) ** 2 + (vertex.co[2] - target_vertex[2]) ** 2)
        if distance < min_distance:
            min_distance = distance
            closest_vertex = vertex

    return closest_vertex


obj = bpy.data.objects["obj"]
splines = bpy.data.objects["curve"].data.splines

for spline in splines:
    for point in spline.points:
        # Get the location of the nearest point
        target_loc = find_closest_vertex(obj, point.co[0:3]).co[0:3]

        vector_to_target = (target_loc[0] - point.co[0], target_loc[1] - point.co[1], target_loc[2] - point.co[2])

        # tilt
        tilt = math.atan2(vector_to_target[1], vector_to_target[0])
        tilt = tilt if tilt > -math.pi else tilt + 2 * math.pi

        print(tilt)
        point.tilt = tilt
$\endgroup$

2 Answers 2

3
$\begingroup$

That won't be a totally perfect result, but you can use the following:

See closest_point_on_mesh for more information.

Once you have the closest face normal, get its angle from the Z axis and use it as a tilt.

obj = bpy.data.objects["obj"]
splines = bpy.data.objects["curve"].data.splines

for spline in splines:
    for point in spline.points:
        # Get the location of the nearest point
        point_co = point.co.xyz
        (hit, loc, norm, face_index) = obj.closest_point_on_mesh(point_co)
        
        tilt = Vector((0,0,1)).angle(norm)

        print(tilt)
        point.tilt = tilt
$\endgroup$
3
$\begingroup$

After upgrading to Blender 4.0, I have found a new solution that combines Geometry Nodes and Python, enabling me to achieve this functionality.

Just select the curve object, and then execute the Python code.

enter image description here

The approximate workflow is as follows: initially, calculate the correct tilt value using Geometry Nodes, and subsequently execute actions through Python to:

  1. Duplicate the object;
  2. Convert it into a mesh (since curves are not compatible with direct application of Geometry Node modifiers);
  3. Transfer the Tilt property.

However, this method suffers from a performance issue due to my limited proficiency in mathematics. Consequently, I have had to resort to an iterative process within Geometry Nodes, which involves extending the normal direction of each point and comparing the distance between that point and the surface of the mesh to incrementally adjust the Tilt value.

I suspect there might be a more direct mathematical approach to calculate the precise Tilt value without requiring iterations. I am hoping someone can assist me with finding such a solution.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .