gate groundwork
[carveJwlIkooP6JGAAIwe30JlM.git] / blender_export.py
1 import bpy, math
2 from ctypes import *
3
4 class model(Structure):
5 _pack_ = 1
6 _fields_ = [("identifier",c_uint32),
7 ("vertex_count",c_uint32),
8 ("indice_count",c_uint32),
9 ("layer_count",c_uint32),
10 ("marker_count",c_uint32)]
11
12 class sdf_primative(Structure):
13 _pack_ = 1
14 _fields_ = [("origin",c_float*4),
15 ("info",c_float*4)]
16
17 class submodel(Structure):
18 _pack_ = 1
19 _fields_ = [("indice_start",c_uint32),
20 ("indice_count",c_uint32),
21 ("vertex_start",c_uint32),
22 ("vertex_count",c_uint32),
23 ("bbx",(c_float*3)*2),
24 ("pivot",c_float*3),
25 ("sdf",sdf_primative),
26 ("sdf_type",c_int32),
27 ("name",c_char*32)]
28
29 class marker(Structure):
30 _pack_ = 1
31 _fields_ = [("co",c_float*3),
32 ( "q",c_float*4),
33 ( "s",c_float*3),
34 ("name",c_char*32)]
35
36 class model_vert(Structure):
37 _pack_ = 1
38 _fields_ = [("co",c_float*3),
39 ("norm",c_float*3),
40 ("colour",c_float*4),
41 ("uv",c_float*2)]
42
43 def v4_dot( a, b ):
44 return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*a[3]
45
46 def v4_length( a ):
47 return math.sqrt( v4_dot(a,a) )
48
49 def m3x3_mul( a, b, d ):
50 a00 = a[0][0]
51 a01 = a[0][1]
52 a02 = a[0][2]
53 a10 = a[1][0]
54 a11 = a[1][1]
55 a12 = a[1][2]
56 a20 = a[2][0]
57 a21 = a[2][1]
58 a22 = a[2][2]
59 b00 = b[0][0]
60 b01 = b[0][1]
61 b02 = b[0][2]
62 b10 = b[1][0]
63 b11 = b[1][1]
64 b12 = b[1][2]
65 b20 = b[2][0]
66 b21 = b[2][1]
67 b22 = b[2][2]
68 d[0][0] = a00*b00 + a10*b01 + a20*b02
69 d[0][1] = a01*b00 + a11*b01 + a21*b02
70 d[0][2] = a02*b00 + a12*b01 + a22*b02
71 d[1][0] = a00*b10 + a10*b11 + a20*b12
72 d[1][1] = a01*b10 + a11*b11 + a21*b12
73 d[1][2] = a02*b10 + a12*b11 + a22*b12
74 d[2][0] = a00*b20 + a10*b21 + a20*b22
75 d[2][1] = a01*b20 + a11*b21 + a21*b22
76 d[2][2] = a02*b20 + a12*b21 + a22*b22
77
78 def q_m3x3( q, d ):
79 l = v4_length(q)
80 s = 2.0 if l > 0.0 else 0.0
81 xx = s*q[0]*q[0]
82 xy = s*q[0]*q[1]
83 wx = s*q[3]*q[0]
84 yy = s*q[1]*q[1]
85 yz = s*q[1]*q[2]
86 wy = s*q[3]*q[1]
87 zz = s*q[2]*q[2]
88 xz = s*q[0]*q[2]
89 wz = s*q[3]*q[2]
90 d[0][0] = 1.0 - yy - zz
91 d[1][1] = 1.0 - xx - zz
92 d[2][2] = 1.0 - xx - yy
93 d[0][1] = xy + wz
94 d[1][2] = yz + wx
95 d[2][0] = xz + wy
96 d[1][0] = xy - wz
97 d[2][1] = yz - wx
98 d[0][2] = xz - wy
99
100 def m3x3_q( m, q ):
101 diag = m[0][0] + m[1][1] + m[2][2]
102 if diag >= 0.0:
103 r = math.sqrt( 1.0 + diag )
104 rinv = 0.5 / r
105 q[0] = rinv * (m[1][2] - m[2][1])
106 q[1] = rinv * (m[2][0] - m[0][2])
107 q[2] = rinv * (m[0][1] - m[1][0])
108 q[3] = r * 0.5
109 elif m[0][0] >= m[1][1] and m[0][0] >= m[2][2]:
110 r = math.sqrt( 1.0 - m[1][1] - m[2][2] + m[0][0] )
111 rinv = 0.5 / r
112 q[0] = r * 0.5
113 q[1] = rinv * (m[0][1] + m[1][0])
114 q[2] = rinv * (m[0][2] + m[2][0])
115 q[3] = rinv * (m[1][2] - m[2][1])
116 elif m[1][1] >= m[2][2]:
117 r = math.sqrt( 1.0 - m[0][0] - m[2][2] + m[1][1] )
118 rinv = 0.5 / r
119 q[0] = rinv * (m[0][1] + m[1][0])
120 q[1] = r * 0.5
121 q[2] = rinv * (m[1][2] + m[2][1])
122 q[3] = rinv * (m[2][0] - m[0][2])
123 else:
124 r = math.sqrt( 1.0 - m[0][0] - m[1][1] + m[2][2] )
125 rinv = 0.5 / r
126 q[0] = rinv * (m[0][2] + m[2][0])
127 q[1] = rinv * (m[1][2] + m[2][1])
128 q[2] = r * 0.5
129 q[3] = rinv * (m[0][1] - m[1][0])
130
131 def write_model(name):
132 fp = open(F"/home/harry/Documents/carve/models/{name}.mdl", "wb")
133 collection = bpy.data.collections[name]
134
135 header = model()
136 header.identifier = 0xABCD0000
137 header.vertex_count = 0
138 header.indice_count = 0
139 header.layer_count = 0
140
141 layers = []
142 markers = []
143 vertex_buffer = []
144 indice_buffer = []
145
146 for obj in collection.objects:
147 if obj.type == 'EMPTY':
148 mk = marker()
149 mk.co[0] = obj.location[0]
150 mk.co[1] = obj.location[2]
151 mk.co[2] = -obj.location[1]
152
153 # Convert rotation quat to our space type
154 quat = obj.matrix_world.to_quaternion()
155 mk.q[0] = quat[1]
156 mk.q[1] = quat[3]
157 mk.q[2] = -quat[2]
158 mk.q[3] = quat[0]
159
160 mk.s[0] = obj.scale[0]
161 mk.s[1] = obj.scale[2]
162 mk.s[2] = obj.scale[1]
163 mk.name = obj.name.encode('utf-8')
164
165 markers += [mk]
166 header.marker_count += 1
167
168 elif obj.type == 'MESH':
169 dgraph = bpy.context.evaluated_depsgraph_get()
170 data = obj.evaluated_get(dgraph).data
171 data.calc_loop_triangles()
172 data.calc_normals_split()
173
174 sm = submodel()
175 sm.indice_start = header.indice_count
176 sm.vertex_start = header.vertex_count
177 sm.vertex_count = len(data.vertices)
178 sm.indice_count = len(data.loop_triangles)*3
179 sm.sdf_type = 0
180 sm.pivot[0] = obj.matrix_world.translation[0]
181 sm.pivot[1] = obj.matrix_world.translation[2]
182 sm.pivot[2] = -obj.matrix_world.translation[1]
183
184 for i in range(3):
185 sm.bbx[0][i] = 999999
186 sm.bbx[1][i] = -999999
187
188 if F"{obj.name}.sdf_cone" in bpy.data.objects:
189 cone = bpy.data.objects[F"{obj.name}.sdf_cone"]
190 sm.sdf.origin[0] = cone.location[0]
191 sm.sdf.origin[1] = cone.location[2] + cone.scale[1]*2.0
192 sm.sdf.origin[2] = -cone.location[1]
193 sm.sdf.origin[3] = 0.0
194
195 lo = cone.scale[0]
196 la = cone.scale[1]*2.0
197 lh = math.sqrt(lo*lo+la*la)
198
199 sm.sdf.info[0] = lo
200 sm.sdf.info[1] = la
201 sm.sdf.info[2] = lo/lh
202 sm.sdf.info[3] = la/lh
203
204 sm.sdf_type = 1
205
206 sm.name = obj.name.encode('utf-8')
207
208 for vert in data.vertices:
209 v = model_vert()
210 v.co[0] = vert.co[0]
211 v.co[1] = vert.co[2]
212 v.co[2] = -vert.co[1]
213 v.colour[0] = 1.0
214 v.colour[1] = 1.0
215 v.colour[2] = 1.0
216 v.colour[3] = 1.0
217 vertex_buffer += [v]
218
219 for i in range(3):
220 sm.bbx[0][i] = min( sm.bbx[0][i], v.co[i] )
221 sm.bbx[1][i] = max( sm.bbx[1][i], v.co[i] )
222
223 for l in data.loops:
224 pvert = vertex_buffer[l.vertex_index + sm.vertex_start]
225 norm = l.normal
226 pvert.norm[0] = norm[0]
227 pvert.norm[1] = norm[2]
228 pvert.norm[2] = -norm[1]
229
230 #if data.vertex_colors:
231 # colour = data.vertex_colors.active.data[ l.index ].color
232 # pvert.colour[0] = colour[0]
233
234 if data.uv_layers:
235 uv = data.uv_layers.active.data[ l.index ].uv
236 pvert.uv[0] = uv[0]
237 pvert.uv[1] = uv[1]
238
239 for tri in data.loop_triangles:
240 indice_buffer += [c_uint32(tri.vertices[_]) for _ in range(3)]
241
242 layers += [sm]
243 header.layer_count += 1
244 header.vertex_count += sm.vertex_count
245 header.indice_count += sm.indice_count
246
247 fp.write( bytearray( header ) )
248 for l in layers:
249 fp.write( bytearray(l) )
250 for m in markers:
251 fp.write( bytearray(m) )
252 for v in vertex_buffer:
253 fp.write( bytearray(v) )
254 for i in indice_buffer:
255 fp.write( bytearray(i) )
256
257 fp.close()
258
259 for col in bpy.data.collections["export"].children:
260 write_model( col.name )