bmesh_collision.py
2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import bpy
import bmesh
def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifiers=False):
assert(obj.type == 'MESH')
if apply_modifiers and obj.modifiers:
me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW', calc_tessface=False)
bm = bmesh.new()
bm.from_mesh(me)
bpy.data.meshes.remove(me)
else:
me = obj.data
if obj.mode == 'EDIT':
bm_orig = bmesh.from_edit_mesh(me)
bm = bm_orig.copy()
else:
bm = bmesh.new()
bm.from_mesh(me)
# Remove custom data layers to save memory
for elem in (bm.faces, bm.edges, bm.verts, bm.loops):
for layers_name in dir(elem.layers):
if not layers_name.startswith("_"):
layers = getattr(elem.layers, layers_name)
for layer_name, layer in layers.items():
layers.remove(layer)
if transform:
bm.transform(obj.matrix_world)
if triangulate:
bmesh.ops.triangulate(bm, faces=bm.faces)
return bm
def bmesh_check_intersect_objects(obj, obj2):
assert(obj != obj2)
# Triangulate
bm = bmesh_copy_from_object(obj, transform=True, triangulate=True)
bm2 = bmesh_copy_from_object(obj2, transform=True, triangulate=True)
# If bm has more edges, use bm2 instead for looping over its edges
# (so we cast less rays from the simpler object to the more complex object)
if len(bm.edges) > len(bm2.edges):
bm2, bm = bm, bm2
# Create a real mesh (lame!)
scene = bpy.context.scene
me_tmp = bpy.data.meshes.new(name="~temp~")
bm2.to_mesh(me_tmp)
bm2.free()
obj_tmp = bpy.data.objects.new(name=me_tmp.name, object_data=me_tmp)
scene.objects.link(obj_tmp)
scene.update()
ray_cast = obj_tmp.ray_cast
intersect = False
EPS_NORMAL = 0.000001
EPS_CENTER = 0.01 # should always be bigger
#for ed in me_tmp.edges:
for ed in bm.edges:
v1, v2 = ed.verts
# setup the edge with an offset
co_1 = v1.co.copy()
co_2 = v2.co.copy()
co_mid = (co_1 + co_2) * 0.5
no_mid = (v1.normal + v2.normal).normalized() * EPS_NORMAL
co_1 = co_1.lerp(co_mid, EPS_CENTER) + no_mid
co_2 = co_2.lerp(co_mid, EPS_CENTER) + no_mid
co, no, index = ray_cast(co_1, co_2)
if index != -1:
intersect = True
break
scene.objects.unlink(obj_tmp)
bpy.data.objects.remove(obj_tmp)
bpy.data.meshes.remove(me_tmp)
scene.update()
return intersect