I have a strange problem with a python script. I am generating an object with holes cut out of it in specific locations. The script works well for all of it except for one specific and weird problem. I run a loop for a boolean difference operation and it works for every hole except for my first hole.
I've gone back and stopped the code before the first boolean cut occurs by adding an extra edit mode toggle (to break it) and tried to manually add the difference boolean to generate the hole and it doesn't want to work manually either. I have no idea what is going on - especially since it works on all the other holes and also since it won't even seem to let me do it manually.
My code is attached below. I have no idea why it won't build my first hole - all assistance will be greatly appreciated.
#imports
import bpy
import numpy as np
import math
from array import *
#Definitions
# Calculates Rotation Matrix given euler angles. Need angle in radians.
def eulerAnglesToRotationMatrix(theta) :
R_x = np.array([[1, 0, 0 ],
[0, math.cos(theta[0]), -math.sin(theta[0]) ],
[0, math.sin(theta[0]), math.cos(theta[0]) ]
])
R_y = np.array([[math.cos(theta[1]), 0, math.sin(theta[1]) ],
[0, 1, 0 ],
[-math.sin(theta[1]), 0, math.cos(theta[1]) ]
])
R_z = np.array([[math.cos(theta[2]), -math.sin(theta[2]), 0],
[math.sin(theta[2]), math.cos(theta[2]), 0],
[0, 0, 1]
])
R = np.dot(R_z, np.dot( R_y, R_x ))
return R
#Variables
hemiRadius = 0.3
hemiSegments = 25
hemiRingCount = 25
hemiLocation = (0, 0, 0)
dropRadius = 0.03
dropVertices = 16
#Variables for hole placement.
maxYaw = (75) #degrees
maxPitch = (65) #degrees
radius = hemiRadius #degrees
#Sphere
bpy.ops.mesh.primitive_uv_sphere_add(segments = hemiSegments, ring_count = hemiRingCount, size=hemiRadius, view_align=False, enter_editmode=True, location=hemiLocation)
#Cut sphere in half vertically in the correct plane
#Change plane_co("X", 0.3, 0) to '0' to make it a perfect half of a sphere, increase 'X' to allow more of the other half of the sphere to be present
bpy.ops.mesh.bisect(plane_co=(0.03, 0.3, 0), plane_no=(0.999995, 0.003263, -0), clear_inner=False, clear_outer=True, xstart=681, xend=683, ystart=715, yend=102)
#add subdivide meshes
bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.subdivide(smoothness=0)
#increase thickness
bpy.ops.object.modifier_remove(modifier="Solidify")
bpy.ops.object.modifier_add(type='SOLIDIFY')
bpy.context.object.modifiers["Solidify"].offset = 0
bpy.context.object.modifiers["Solidify"].thickness = 0.02
bpy.ops.object.editmode_toggle()
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Solidify")
bpy.ops.object.editmode_toggle()
###At this point, Hemisphere is built
#Conversion degrees into radians
maxYaw = (maxYaw/180.0)*np.pi #now in radians
maxPitch = (maxPitch/180.0)*np.pi #now in radians
#locations of holes
rollPointsDeg = [[0, 0, 0], #0 center
[0, maxPitch, 0], #1 top mid
[0, maxPitch, maxYaw], #2 top left
[0, 0, maxYaw], #3 mid left
[0, -maxPitch, maxYaw], #4 bot left
[0, -maxPitch, 0], #5 bot mid
[0, -maxPitch, -maxYaw], #6 bot rig
[0, 0, -maxYaw], #7 mid rig
[0, maxPitch, -maxYaw]] #8 top rig
#location of holes
rollPoints = [[-radius, 0, 0], #0
[0, 0, 0], #1
[0, 0, 0], #2
[0, 0, 0], #3
[0, 0, 0], #4
[0, 0, 0], #5
[0, 0, 0], #6
[0, 0, 0], #7
[0, 0, 0]] #8
#the rotational matrix variable
rotMat = np.array([[0,0,0],[0,0,0],[0,0,0]])
#Rotation Matrix Loop
i=1
while i < 9:
rotMat = eulerAnglesToRotationMatrix(rollPointsDeg[i]) #converts the rotMat into the rotational matrix
rollPoints[i] = np.dot (rotMat, rollPoints[0]) #dot product of rotMatrix and rollPoints[0]
i += 1
#comment out this line if getting errors from blender about <<operation cannot performe in edit mode
bpy.ops.object.editmode_toggle()
#Loop adding circles in precise location and orientation
k = 0
while k < 9:
bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
exitStatus = bpy.ops.mesh.primitive_circle_add(vertices=16, radius=0.03)
scj = bpy.context.scene
# The added circle will be the active object after it is created
ob = bpy.context.object
me = ob.data
# If you want to move your object, simply set its location thus:
ob.location = ( rollPoints[k][0], rollPoints[k][1],rollPoints[k][2] )
# And you can rotate the object the same way
# Note that you need to use radians rather than angles here
ob.rotation_euler = (0*(np.pi/2), (np.pi/2) + rollPointsDeg[k][1], rollPointsDeg[k][2])
#Now apply shrinkwrap after orientations are correct
bpy.ops.object.modifier_add(type='SHRINKWRAP')
bpy.context.object.modifiers["Shrinkwrap"].target = bpy.data.objects["Sphere"]
bpy.context.object.modifiers["Shrinkwrap"].wrap_method = 'PROJECT'
bpy.context.object.modifiers["Shrinkwrap"].use_project_z = True
bpy.context.object.modifiers["Shrinkwrap"].use_negative_direction = True
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Shrinkwrap")
#weird prep-stuff needed to make boolean operation work correctly:
#moving circles within the sphere to allow proper difference boolean operation
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={"mirror":False}, TRANSFORM_OT_translate={"value":(0, 0, 0.09883128), "constraint_axis":(False, False, True), "constraint_orientation":'LOCAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})
bpy.ops.object.editmode_toggle()
bpy.ops.transform.translate(value=(9.31323e-010, -2.09548e-009, -0.0348931), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
#boolean difference operation
hemmy = bpy.data.objects['Sphere']
bpy.context.scene.objects.active = hemmy
bpy.ops.object.select_all(action='TOGGLE')
bpy.ops.object.select_all(action='TOGGLE')
bpy.ops.object.modifier_apply(modifier="Auto Boolean")
bpy.ops.btool.auto_difference(solver='BMESH')
k +=1
