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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import bpy
from mathutils import Vector
def fmt3(vec3):
return "%.10f %.10f %.10f"%(vec3.x, vec3.y, vec3.z)
def fmt_plane(plane3dots):
return "( %s ) ( %s ) ( %s )"%(fmt3(plane3dots[0]), fmt3(plane3dots[1]), fmt3(plane3dots[2]))
def fmt_tex(tev, toff):
return "[ %s %.1f ]"%(fmt3(tev), toff)
def fmt_face(plane3dots, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY):
return "%s %s %s %s %s"%(
fmt_plane(plane3dots), tename,
fmt_tex(tev1, teoff1),
fmt_tex(tev2, teoff2),
fmt3(Vector([rot, scaleX, scaleY]))
)
def output_entity_start(dict_props):
print("{")
for k,v in dict_props.items():
print("\t\"%s\" \"%s\""%(k,v))
def output_brush_start():
print("\t{")
def output_brush_face(plane3dots, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY):
print("\t%s"%fmt_face(plane3dots, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY))
def output_brush_end():
print("\t}")
def output_entity_end():
print("}")
def normal(plane3dots):
v01 = plane3dots[1] - plane3dots[0]
v02 = plane3dots[2] - plane3dots[0]
n = v01.cross(v02)
n.normalize()
return n
def flip(plane3dots):
tmp = plane3dots[2]
plane3dots[2] = plane3dots[1]
plane3dots[1] = tmp
def debug(fano,plane3dots):
fano.normalize()
print(fano)
v01 = plane3dots[1] - plane3dots[0]
v02 = plane3dots[2] - plane3dots[0]
n = v01.cross(v02)
n.normalize()
print(n)
print(fano-n)
print()
worldspawn_props = {
'classname': 'worldspawn',
'sounds': 1,
'MaxRange': 4096,
'mapversion': 220,
'wad': '\\half-life\\valve\\xeno.wad;\\half-life\\valve\\decals.wad;\\half-life\\valve\\halflife.wad;\\half-life\\valve\\liquids.wad'
}
blender_to_map_scale_factor = 100
# https://developer.valvesoftware.com/wiki/MAP_file_format
output_entity_start(worldspawn_props)
for o in bpy.data.scenes[0].objects:
if o.type != 'MESH':
continue
mat_to_map = o.matrix_world * blender_to_map_scale_factor
mesh = o.data
mesh.update(calc_tessface=True)
for fa in mesh.tessfaces:
output_brush_start()
tename="AAATRIGGER"
tev1 = Vector([1,0,0])
teoff1 = 0
tev2 = Vector([0,-1,0])
teoff2 = 0
rot = 0
scaleX = 1
scaleY = 1
# Make a brush in .map for each face in blender
# Brushes are (strangely) defined as a set of intersecting planes in .map
# Planes are defined with 3 3D points belonging to it
# "They must be in a clockwise order when facing the outside of the plane
# that is, the side that points outwards from the brush"
brfront = [None,None,None]
brback = [None,None,None]
# For now this code take the 3 first vectices of the face
# TODO This can cause troubles if they are colinear or with have narrow angle
for i in [0,1,2]:
vi = mesh.vertices[fa.vertices[i]].co
# front plane in brush will match face in blender (in global coords, with a scale factor)
brfront[i] = mat_to_map * vi
# back plane will be 1 (map) unit inside (normal facing outside, so substract it)
brback[2-i] = mat_to_map * ( vi - fa.normal / blender_to_map_scale_factor )
# Check if coords are in clockwise order, else flip them
fano = mat_to_map.to_3x3() * fa.normal
frno = normal(brfront)
epsilon = 0.1
if ( (fano - frno).length_squared > epsilon ):
flip(brfront)
flip(brback)
#print("Front&Back Flipped")
#debug(mat_to_map.to_3x3() * fa.normal, front)
output_brush_face(brfront, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY)
#debug(mat_to_map.to_3x3() *-fa.normal, back)
output_brush_face(brback, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY)
# make 1 side face in brush per blender edge
for i,j in fa.edge_keys:
brside = [None,None,None]
brside[0] = mat_to_map * ( mesh.vertices[i].co )
brside[1] = mat_to_map * ( mesh.vertices[j].co )
brside[2] = mat_to_map * ( mesh.vertices[j].co - fa.normal )
# Let have a plane define by a point A and a normal n
# Let M a point in space. M is on the plane if AM.n = 0
# Now we want to know if the "side" face normal is poiting outwards of the brush (<0)
# Take A = side[0], M = fa.center (that is inside the brush), n = normal(side)
if ( (mat_to_map * fa.center - brside[0]).dot(normal(brside)) < 0):
flip(brside)
#print("Side Flipped")
#print(normal(side))
output_brush_face(brside, tename, tev1, teoff1, tev2, teoff2, rot, scaleX, scaleY)
output_brush_end()
output_entity_end()
|