1
$\begingroup$

I would like to achieve this with python script in blender:

  1. select a face in edit mode, the script will get and store the orientation of the normal of that face. enter image deさ

2.create a cone or import an object at location, and set its rotation so its Z axis is aligned with normal of the previously face. enter image description here

Following code is what i pieced together so far, it's not working as expected. Not good at math and not really knowing how the orientation is calculated, so i can only logically guess hows things works from here and there.

Hope someone here could be nice enough to walk me through and correct it for me, this is the best i can get as a beginner in coding. Thx~

import bpy
import mathutils

bpy.context.area.type = 'VIEW_3D' 
bpy.context.space_data.transform_orientation = 'NORMAL'

# object to align i.e. the selected face(in edit mode)
obj = bpy.context.active_object
# normal vector of the selected face
norm = bpy.context.active_object.data.polygons[0].normal
diff = norm.rotation_difference(mathutils.Vector((0, 0, 1)))
# set quat orientation
obj.rotation_quaternion = diff

# move cursor to selected face
bpy.ops.view3d.snap_cursor_to_selected() 
# save location of cursor
my_location=bpy.context.scene.cursor_location

# quit edit mode
bpy.ops.object.mode_set(mode='OBJECT')
# to simplify for this example i create a cone here
#(the original idea was to import an stl object here)
bpy.ops.mesh.primitive_cone_add(location=my_location)
# apply the quat orientation/rotation to the cone 
bpy.context.active_object.rotation_mode='QUATERNION'
bpy.context.active_object.rotation_quaternion= obj.rotation_quaternion

bpy.context.area.type = 'TEXT_EDITOR'

Tried look into this thread but cannot make sense of it: Rotation by normal

$\endgroup$
1
  • $\begingroup$ Is this not what you wanted, to place a cone in the middle of face? If you're interested in an easy non-script way to insert a cone in the middle of each face with normal orientation you can do it by parenting the cone to the object and activating Duplication in Face mode in the object settings. I can post an answer to that if it's relevant to you. But otherwise expand on what's the issue with your current code, goals and results. $\endgroup$
    – kheetor
    Commented Apr 20, 2018 at 10:17

1 Answer 1

2
$\begingroup$

Firstly, I'm not clear you are getting the normal of the selected face as opposed to the first face.

Quaternions are tricky. I have found assigning to obj.rotation_quaternion does nothing, whereas assigning to obj.rotation_euler does, but I'm not sure I don't think I set rotation mode as you do at the end.

I don't think there is any value in setting the rotation of the first object to the selected face, this apart from not working (perhaps because of the above) doesn't help align the cone.

And I've got in the habit of using a bmesh, but you might be able to do it directly from the data. But once you have the rotation Quaternion, you have to multiply the object's existing rotation by the inverse of the Quaternion. Well, it worked for me.

# This example assumes we have a mesh object in edit-mode

import bpy
import bmesh
import mathutils

# Get the active mesh (assumes starting in edit mode)
obj = bpy.context.edit_object
me = obj.data
coneradius=1     # Im not sure how you plan to scale the cone.
Up=mathutils.Vector((0,0,1))

# Get a BMesh representation
bm = bmesh.from_edit_mesh(me)
selected_faces=[face for face in bm.faces if face.select]
if len(selected_faces)>0:
    norm=selected_faces[0].normal
    my_location=selected_faces[0].calc_center_median()
    # convert this to a rotation quaternion    
    Qrot=norm.rotation_difference(Up)

    #Add the cone in object mode
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.mesh.primitive_cone_add(location=my_location)
    cone=bpy.context.object
    cone.rotation_mode='QUATERNION'
    cone.rotation_quaternion*=Qrot.inverted()

    # Im not sure how you plan to scale the cone and translate it.
$\endgroup$
2
  • $\begingroup$ it works! i will hv to test and mess around with this code to understand more about the logic behind this. What is the difference between "normal of the selected face" as opposed to"the first face"? $\endgroup$
    – adrian li
    Commented Apr 20, 2018 at 12:41
  • $\begingroup$ bpy.context.active_object.data.polygons I expect is a list of polygons, the first of which bpy.context.active_object.data.polygons[0] might be who knows which face, but probably not the face you have selected in edit view. $\endgroup$
    – Tonyfai
    Commented Apr 20, 2018 at 12:46

You must log in to answer this question.

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