본문으로 바로가기

예전에 저는 스크립트로 CAD를 하는 OpenSCAD를 잠시 봤던 적이 있습니다.[바로가기] 아무래도 기계 엔지니어가 아니다 보니 멋드러진 툴로 현란하게 그리지 못하고 저렇게 코드를 이용한 CAD가 더 흥미롭더라구요^^. 뭐 그리고 한 동안 잊고 있었는데... 최근 파이썬 로보틱스라는 책[바로가기]을 읽다가 블렌더(Blender) 이야기가 나오더라구요. 그리고 기억했죠.. 저도 블렌더를 소개한 적이 있었더라구요^^[바로가기] 뭐 그때는 리눅스에 정말 초..초 간단히 설치하는게 내용이었지만요^^ 이 블렌더에는 Python 스크립트로 CAD 작업을 가능하게 했더라구요... 아~ 그래서 역시 저 답게 또 따라하기를 했죠... 도대체 전 언제쯤 이거 안하고 정말 멋진 내용을 올릴까요?ㅠㅠ.

뭐 아무튼~... Blender의 실행화면입니다.

저 부분을 바꿔서...

Scripting으로 바꾸면 Python 코드를 입력할 수 있는 창이 나타납니다.

그리고 교재에서 제공하는 코드를 붙여넣었죠^^

import bpy

#This function will draw base plate
def Draw_Base_Plate():
    #Added two cubes for cutting sides of base plate
    
    bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(0.175,0,0.09))
    bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(-0.175,0,0.09))

    #Adding base plate
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.09))
    
    #Adding booleab difference modifier from first cube
    
    bpy.ops.object.modifier_add(type='BOOLEAN')
    bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube"]
    bpy.ops.object.modifier_apply(modifier="Boolean")

    #Adding booleab difference modifier from second cube
    
    bpy.ops.object.modifier_add(type='BOOLEAN')
    bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube.001"]
    bpy.ops.object.modifier_apply(modifier="Boolean")

    #Deselect cylinder and delete cubes
    bpy.ops.object.select_pattern(pattern="Cube")
    bpy.ops.object.select_pattern(pattern="Cube.001")
    bpy.data.objects['Cylinder'].select = False
    bpy.ops.object.delete(use_global=False)
    
#This function will draw motors and wheels
def Draw_Motors_Wheels():
    #Create first Wheel
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07))
    #Rotate
    bpy.context.object.rotation_euler[1] = 1.5708
    #Transalation
    bpy.context.object.location[0] = 0.135

    #Create second wheel
    bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07))
    #Rotate
    bpy.context.object.rotation_euler[1] = 1.5708
    #Transalation
    bpy.context.object.location[0] = -0.135

    #Adding motors
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(0.075,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(-0.075,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    #Adding motor shaft
    bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(0.12,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(-0.12,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    #Addubg Caster Wheel
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,0.125,0.065))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,-0.125,0.065))
    
    #Adding Kinect
    
    bpy.ops.mesh.primitive_cube_add(radius=0.04, location=(0,0,0.26))    
    
#Draw middle plate
def Draw_Middle_Plate():
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.22))

#Adding top plate
def Draw_Top_Plate():
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.37))

#Adding support tubes
def Draw_Support_Tubes():
    #Cylinders
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,-0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,-0.09,0.23))


#Main code

if __name__ == "__main__":
    Draw_Base_Plate()
    Draw_Motors_Wheels()
    Draw_Middle_Plate()
    Draw_Top_Plate()
    Draw_Support_Tubes()

그리고 Run Script를 해주면~~~

저렇게 .. 뭔가 멋진 모양이 나타납니다. 우와~~~~ 일단 감탄 5초 한다음에.. 그래도 튜토리얼인데 살짝 들여다 볼까요^^ 아 그전에 블렌더의 Python API에 대한 문서[바로가기]를 가보시면 뭐 다있는 내용입니다.

#Draw middle plate
def Draw_Middle_Plate():
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.22))

#Adding top plate
def Draw_Top_Plate():
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.37))

심플합니다. 중간과 윗판을 그린것인데... 딱 봐도 뭔지 알 정도로 cylinder로 구현되어 있습니다. 반지름(radius)과 길이(depth)를 지정하고 위치를 잡아주면 됩니다.^^.

#Adding support tubes
def Draw_Support_Tubes():
    #Cylinders
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(-0.09,-0.09,0.23))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.007,depth=0.30, location=(0.09,-0.09,0.23))

저건 기둥들을 잡아 준 것인데 역시 cylinder로 그렸습니다.^^.

아~~ 저부분만 따로 그린 코드는

#This function will draw motors and wheels
def Draw_Motors_Wheels():
    #Create first Wheel
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07))
    #Rotate
    bpy.context.object.rotation_euler[1] = 1.5708
    #Transalation
    bpy.context.object.location[0] = 0.135

    #Create second wheel
    bpy.ops.mesh.primitive_cylinder_add(radius=0.045,depth=0.01, location=(0,0,0.07))
    #Rotate
    bpy.context.object.rotation_euler[1] = 1.5708
    #Transalation
    bpy.context.object.location[0] = -0.135

    #Adding motors
    bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(0.075,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.018,depth=0.06, location=(-0.075,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    #Adding motor shaft
    bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(0.12,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    bpy.ops.mesh.primitive_cylinder_add(radius=0.006,depth=0.04, location=(-0.12,0,0.075))
    bpy.context.object.rotation_euler[1] = 1.5708
    
    #Addubg Caster Wheel
    bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,0.125,0.065))
    bpy.ops.mesh.primitive_cylinder_add(radius=0.015,depth=0.05, location=(0,-0.125,0.065))
    
    #Adding Kinect
    bpy.ops.mesh.primitive_cube_add(radius=0.04, location=(0,0,0.26))    

좀 길긴 하지만, 두 바퀴는 cylinder로 그린다음 y축 중심으로 90도 회전하고, 위치를 다시 잡아준 것입니다. 그리고, 모터와 앞 뒤 바퀴용인 캐스터를 그려넣은 것이죠^^

이제 base판인데요.. 이 판은 꽤 재미있게 그립니다. 먼저 저런 cube를 놓고...

원판을 cylinder로 그린다음... 원판에서 cube를 빼버린 겁니다.^^

#This function will draw base plate
def Draw_Base_Plate():
    #Added two cubes for cutting sides of base plate
    
    bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(0.175,0,0.09))
    bpy.ops.mesh.primitive_cube_add(radius=0.05, location=(-0.175,0,0.09))

    #Adding base plate
    bpy.ops.mesh.primitive_cylinder_add(radius=0.15,depth=0.005, location=(0,0,0.09))
    
    #Adding booleab difference modifier from first cube
    
    bpy.ops.object.modifier_add(type='BOOLEAN')
    bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube"]
    bpy.ops.object.modifier_apply(modifier="Boolean")

    #Adding booleab difference modifier from second cube
    
    bpy.ops.object.modifier_add(type='BOOLEAN')
    bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["Cube.001"]
    bpy.ops.object.modifier_apply(modifier="Boolean")

    #Deselect cylinder and delete cubes
    bpy.ops.object.select_pattern(pattern="Cube")
    bpy.ops.object.select_pattern(pattern="Cube.001")
    bpy.data.objects['Cylinder'].select = False
    bpy.ops.object.delete(use_global=False)

그러면...

이 그림이 되는 거죠^^

이제 다 그렸네요^^

이걸 STL파일로 export 시키면 저렇게 이쁘당한 모양을 얻을 수 있습니다. 아 3D 데이터를 바로 확인하기에는 별도로 Mesh Lab[바로가기]도 괜찮다고 하네요

괜찮네요~~~ 이제 도면 작업도 간단한 거라면 좀 더 편하게 할 수 있을듯 하네요^^


댓글을 달아 주세요

  1. BlogIcon 핑구야 날자 2016.07.16 07:34 신고

    3D는 언제봐도 리얼한 느낌때문에 더 보게 되요

  2. BlogIcon 여행쟁이 김군 2016.07.16 13:48 신고

    요즘 3D 프린터기 때문에 눈여겨 보는데~ 3D 모델을 이렇게 직접 그리시다니! 너무 멋지네요

  3. BlogIcon 구차니 2016.10.21 13:12 신고

    헉!!! 이런 방법이 !!(깨달은 척)
    블렌더 조금 만져 보려다가 3d에 대한 이해가 무언가 그려야 한다는 목적이 없다 보니
    흐지부지 하고.. 잠시 블렌더 내장 게임 엔진이 있다는걸 들어서 공부하려다가
    또 흐지부지 되는데 하나하나 파고 드시는 모습이 부럽습니다 ㅠㅠ

    • BlogIcon PinkWink 2016.10.21 16:03 신고

      블렌더... 꽤 좋은것 같아요.. 만약 지금 제가 대학생이라면 꽤 재미난 프로젝트를 많이 해볼 수 있을것 같아요^^