4
$\begingroup$

I have a problem with a python script for generating an object consisting of two parts combined with the union modifier.

This is a stripped down part of the code:

import bpy
import math
import mathutils
from mathutils import Vector, Matrix

####################################################################

verts = [
    Vector((0.0, 1.6738300323486328, 0.0)),
    Vector((0.0, -1.6738300323486328, 0.0)),
    Vector((3.849679946899414, -1.929069995880127, 0.0)),
    Vector((3.849679946899414, 1.929069995880127, 0.0)),
    Vector((0.2250913381576538, 1.455641746520996, -0.3000001907348633)),
    Vector((0.2250913381576538, -1.455641746520996, -0.3000001907348633)),
    Vector((3.6170783042907715, -1.6805357933044434, -0.2999999523162842)),
    Vector((3.6170783042907715, 1.6805355548858643, -0.2999999523162842))]

faces = ((0,1,2,3), (7,6,5,4), (1,0,4,5), (3,2,6,7), (0,3,7,4), (2,1,5,6))

origin = Vector((0, 0.0000, 2.0))

# Delete all
bpy.ops.object.select_all(action = 'SELECT')
bpy.ops.object.delete()
for item in bpy.data.objects:
    bpy.data.objects.remove(item)
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

# Create mesh and object
name = 'klotz'
me = bpy.data.meshes.new(name+'Mesh')
obj = bpy.data.objects.new(name, me)
obj.location = origin
obj.show_name = True

# Link object to scene and make active
scn = bpy.context.scene
scn.objects.link(obj)
scn.objects.active = obj
obj.select = True

# Create mesh from given verts, faces.
me.from_pydata(verts, [], faces)
# Update mesh with new data
me.update()
bpy.context.scene.update()

# Rotate local object coordinate system
rot_mat = mathutils.Matrix(
    ((0.0000, 1.0000,  0.0000, 0.0000),
    (1.0000, 0.0000,  0.0000, 0.0000),
    (0.0000, 0.0000, -1.0000, 0.0000),
    (0.0000, 0.0000,  0.0000, 1.0000)))

# Rotate object vertices in opposite direction
me = obj.data
me.transform(rot_mat.inverted())
bpy.context.scene.update()
# Update object matrix applying rotation
obj.matrix_world *= rot_mat
bpy.context.scene.update()


nasen_w = 0.5
nasen_d = 0.6
nasen_h = 0.3  ## <== sensitiv to nasen_h
nasen_pos = Vector((0.5579, 0.2000, 0.15))

bpy.ops.mesh.primitive_cube_add(location=nasen_pos)
nase = bpy.context.active_object
nase.scale = (nasen_w/2,nasen_d/2,nasen_h/2)
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
bpy.context.scene.update()
nase.matrix_world = obj.matrix_world.normalized()

# union of klotz and nase
if 0:
    modifier = obj.modifiers.new('Modifier', 'BOOLEAN')
    modifier.object = nase
    modifier.operation = 'UNION'
    bpy.context.scene.objects.active = obj
    bpy.ops.object.modifier_apply(apply_as='DATA', modifier=modifier.name)

    bpy.context.scene.update()
    scene = bpy.context.scene
    scene.objects.unlink(nase)

As shown, the script generates two object, a flat truncated pyramid and small box.

before union

When I try to combine these two object with an union modifier by replacing the

if 0:

in the last code block in line 79 with an

if 1:

the truncated pyramid vanishes, leaving a small piece, which looks like the difference of the two objects, not the union.

after union

Also I get error messages:

group 0x7f145b12ecd0 is unclassified!
group 0x7f145b12ebf0 is unclassified!
group 0x7f145b12ecd0 is unclassified!
group 0x7f145b12ebf0 is unclassified!

This error is sensitive to the height of the box. If this height is equal to the height of the pyramid (the upper and lower faces are then coplanar to the upper and lower faces of the pyramid) the error occurs, if I change the height a little bit, in line 68 for example:

nasen_h = 0.3  ## <== sensitiv to nasen_h

to

nasen_h = 0.2999  ## <== sensitiv to nasen_h

the error vanishes. The error is also dependent of the coordinate transformations (rot_mat) and the postion (origin) of the object.

I tried this with blender version 2.76 and 2.68a. I also checked the normals of the two objects, they seem to be ok. Has anyone an idea, what I'm missing?

Many thanks!

$\endgroup$
  • $\begingroup$ What happens if you replace the 0 in line 79 with a 2? I'm just thinking, there are three types of Boolean operation you can do with that modifier: Difference, Union, and Intersect. So maybe you have only tried two of the three? $\endgroup$ – Mentalist Oct 29 '15 at 12:40
  • $\begingroup$ it might be worth your time filling a bugreport about this, ideasman42 (who implemented the Carve Library as the boolean back end for the modifier) has done some work to rewrite the boolean code -- I think edge cases like this are interesting for testing on code.. and worth having an answer based on how the code works. $\endgroup$ – zeffii Nov 28 '15 at 15:14
1
$\begingroup$

It appears you're stretching the limit a bit with the accuracy of the Boolean modifier here. Your two objects have identical height and positions, which confuses the modifier as to which part is in and which is outside the intersection area.

If absolute mathematical accuracy isn't all too important to you, you can easily solve this by moving the box object a tiny bit on the Z axis - as you already discovered.

$\endgroup$
  • $\begingroup$ Thanks for your answer. My model contains a lot of such cases where objects with coplanar faces are unified or subtracted. After shifting these a bit around, the boolean modifiers seem to work. But I wonder still why this is necessary: unifying two standard cubes of the same height works. With difference modifiers I could imagine numerical difficulties, but for the unify modifier? For the parts of the object which are located almost at the same place it shouldn't matter which object is the "outer" one. The vertices of the pyramid belong clearly to the outer hull and shouldn't be deleted. $\endgroup$ – Corvin Oct 31 '15 at 9:01

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.