2
$\begingroup$

I'm trying to find a way to place an object on the selected face from another object according the normal face.

I'd like the local orientation of my first object correspond to the normals of the selected face from my second object.

This is my code.

import bpy
import bmesh
from mathutils import Vector


class TestPanel(bpy.types.Panel):
    bl_idname = "object.test_panel"
    bl_label = "Test Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'


    def draw(self, context):
        layout = self.layout
        layout.operator("object.clone_object", text="Add Suzanne")



class AddCloneObject(bpy.types.Operator):
    bl_idname = "object.clone_object"
    bl_label = "Clone object"

    def execute(self, context):

        if context.object.mode == 'EDIT':
           bpy.ops.object.mode_set(mode='OBJECT')
           obj = bpy.context.active_object

           bm = bmesh.new()
           bm.from_mesh(obj.data)

           selected_faces = [f for f in bm.faces if f.select]

           for face in selected_faces:

               face_location = face.calc_center_median() 
               loc_world_space = obj.matrix_world * Vector(face_location) 
               z = Vector((0,0,1))

               angle = face.normal.angle(z)
               axis = z.cross(face.normal)
               bpy.context.scene.cursor_location = loc_world_space

               bpy.ops.mesh.primitive_monkey_add(radius=0.5) 

               bpy.ops.transform.rotate(value=angle, axis=axis)


               print("face location = ", loc_world_space)
               print("angle = ", angle)
               print("axis = ", axis)
               print("Suzanne = ", context.active_object.matrix_world)

           bm.to_mesh(obj.data)
           bm.free()

           return {'FINISHED'}

       else:
           self.report({'INFO'}, "Need to be in edit_mode")

           return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()

The X and Y axis are good, but the Z axis seems not to undergo rotation.

$\endgroup$
2
$\begingroup$

Made a couple of changes to this script, the main one is using the Vector.rotation_difference method instead of the angle method. This one calculates rotation in all 3 axes.

import bpy
import bmesh
from mathutils import Vector
from math import degrees # Added for more readable printing of rotation angles

class TestPanel(bpy.types.Panel):
    bl_idname = "object.test_panel"
    bl_label = "Test Panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout
        layout.operator("object.clone_object", text="Add Suzanne")


class AddCloneObject(bpy.types.Operator):
    bl_idname = "object.clone_object"
    bl_label = "Clone object"

    def execute(self, context):

        if context.object.mode == 'EDIT':
           bpy.ops.object.mode_set(mode='OBJECT')
           obj = bpy.context.active_object

           bm = bmesh.new()
           bm.from_mesh(obj.data)

           selected_faces = [f for f in bm.faces if f.select]

           for face in selected_faces:

               face_location = face.calc_center_median() 
               loc_world_space = obj.matrix_world * Vector(face_location) 
               z = Vector((0,0,1))

               # Changes start here
               rot = z.rotation_difference( face.normal ).to_euler()
               bpy.context.scene.cursor_location = loc_world_space

               bpy.ops.mesh.primitive_monkey_add(radius=0.5) 

               bpy.context.object.rotatation_euler = rot

               print("face location = ", loc_world_space)
               print("rotation = ", [degrees(a) for a in rot] )
               print("Suzanne = ", context.active_object.matrix_world)
               # And End here

           bm.to_mesh(obj.data)
           bm.free()

           return {'FINISHED'}

       else:
           self.report({'INFO'}, "Need to be in edit_mode")

           return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ Thanks for your answer, but the probleme stay the same. The Z axis got the good direction but his rotation value is not the same as the Z axis of the normal face :( $\endgroup$ – pistiwique Dec 12 '15 at 12:31
  • $\begingroup$ I see, shame. Will have another look when I can. $\endgroup$ – TLousky Dec 12 '15 at 15:29
  • $\begingroup$ Thanks, but i finally find the solution in the answer of CoDEmanX from this question : blender.stackexchange.com/questions/7150/… $\endgroup$ – pistiwique Dec 12 '15 at 18:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.