1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2019 Jonathan Dent, The appleseedhq Organization
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28
29 // appleseed.renderer headers.
30 #include "renderer/api/object.h"
31
32 // appleseed.foundation headers.
33 #include "foundation/platform/python.h"
34
35 // Standard headers.
36 #include <cstdint>
37
38 namespace bpy = boost::python;
39 using namespace foundation;
40 using namespace renderer;
41
42 namespace
43 {
44 // Blender data structures.
45 // https://developer.blender.org/diffusion/B/browse/master/source/blender/makesdna/DNA_meshdata_types.h
46
47 // Blender 2.79 structures.
48 struct MFace
49 {
50 unsigned int v[4];
51 short mat_nr;
52 char edcode, flag;
53 };
54
55 struct MVert
56 {
57 float co[3];
58 short no[3];
59 char flag, bweight;
60 };
61
62 struct MTFace
63 {
64 float uv[4][2];
65 void *tpage;
66 char flag, transp;
67 short mode, tile, unwrap;
68 };
69
70 // Blender 2.8 structures.
71 struct MLoop
72 {
73 // Vertex index.
74 unsigned int v;
75 unsigned int e;
76 };
77
78 struct MLoopTri
79 {
80 // Vertex id's.
81 unsigned int tri[3];
82 unsigned int poly;
83 };
84
85 struct MLoopUV
86 {
87 float uv[2];
88 int flag;
89 };
90
91 struct MPoly
92 {
93 int loopstart;
94 int totloop;
95 short mat_nr;
96 char flag, pad;
97 };
98 }
99
100
101 //
102 // The following function takes a series of pointers to Blender mesh data
103 // and modifies the appleseed MeshObject entity.
104 //
105 // Arguments:
106 //
107 // blender_mesh: the appleseed MeshObject created earlier in the export process
108 // bl_vert_count: the number of vertices in the mesh
109 // bl_vert_ptr: a string pointer to the first element of the vertex array
110 // (Same template applies to mesh faces.)
111 //
112
export_mesh_blender79(MeshObject * blender_mesh,const size_t bl_vert_count,const uintptr_t bl_vert_ptr,const size_t bl_faces_count,const uintptr_t bl_faces_ptr,const uintptr_t bl_uv_ptr,const bool export_normals,const bool export_uvs)113 void export_mesh_blender79(
114 MeshObject* blender_mesh,
115 const size_t bl_vert_count,
116 const uintptr_t bl_vert_ptr,
117 const size_t bl_faces_count,
118 const uintptr_t bl_faces_ptr,
119 const uintptr_t bl_uv_ptr,
120 const bool export_normals,
121 const bool export_uvs)
122 {
123 // Convert uintptr_t numbers to actual pointers.
124 const MVert* bl_vertices = reinterpret_cast<MVert*>(bl_vert_ptr);
125 const MFace* bl_faces = reinterpret_cast<MFace*>(bl_faces_ptr);
126 const MTFace* bl_uv_faces = reinterpret_cast<MTFace*>(bl_uv_ptr);
127
128 blender_mesh->reserve_vertices(bl_vert_count);
129 blender_mesh->reserve_triangles(bl_faces_count);
130
131 // Push vertices.
132 for (size_t vertex_index = 0; vertex_index < bl_vert_count; ++vertex_index)
133 {
134 const MVert& vert = bl_vertices[vertex_index];
135 blender_mesh->push_vertex(GVector3(vert.co[0], vert.co[1], vert.co[2]));
136 }
137
138 // Push normals.
139 if (export_normals)
140 {
141 blender_mesh->reserve_vertex_normals(bl_vert_count);
142 for (size_t vertex_index = 0; vertex_index < bl_vert_count; ++vertex_index)
143 {
144 const MVert& vert = bl_vertices[vertex_index];
145 blender_mesh->push_vertex_normal(normalize(GVector3(vert.no[0], vert.no[1], vert.no[2])));
146 }
147 }
148
149 // Push triangles.
150 for (size_t face_index = 0; face_index < bl_faces_count; ++face_index)
151 {
152 const MFace& face = bl_faces[face_index];
153 blender_mesh->push_triangle(Triangle(face.v[0], face.v[1], face.v[2], face.mat_nr));
154 }
155
156 // Tie vertex normals to mesh faces.
157 if (export_normals)
158 {
159 for (size_t face_index = 0; face_index < bl_faces_count; ++face_index)
160 {
161 const MFace& face = bl_faces[face_index];
162 Triangle& tri = blender_mesh->get_triangle(face_index);
163 tri.m_n0 = face.v[0];
164 tri.m_n1 = face.v[1];
165 tri.m_n2 = face.v[2];
166 }
167 }
168
169 // Tie uv coordinates to mesh faces.
170 if (export_uvs)
171 {
172 uint32 uv_vertex_index = 0;
173 blender_mesh->reserve_tex_coords(bl_vert_count);
174 for (size_t face_index = 0; face_index < bl_faces_count; ++face_index)
175 {
176 const MTFace& tex_face = bl_uv_faces[face_index];
177 Triangle& tri = blender_mesh->get_triangle(face_index);
178 blender_mesh->push_tex_coords(GVector2(tex_face.uv[0][0], tex_face.uv[0][1]));
179 tri.m_a0 = uv_vertex_index++;
180
181 blender_mesh->push_tex_coords(GVector2(tex_face.uv[1][0], tex_face.uv[1][1]));
182 tri.m_a1 = uv_vertex_index++;
183
184 blender_mesh->push_tex_coords(GVector2(tex_face.uv[2][0], tex_face.uv[2][1]));
185 tri.m_a2 = uv_vertex_index++;
186 }
187 }
188 }
189
export_mesh_blender79_pose(MeshObject * blender_mesh,const size_t pose,const size_t bl_vert_count,const uintptr_t bl_vert_ptr,const bool export_normals)190 void export_mesh_blender79_pose(
191 MeshObject* blender_mesh,
192 const size_t pose,
193 const size_t bl_vert_count,
194 const uintptr_t bl_vert_ptr,
195 const bool export_normals)
196 {
197 // Convert uintptr_t numbers to actual pointers.
198 const MVert* bl_vertices = reinterpret_cast<MVert*>(bl_vert_ptr);
199
200 // Push vertices.
201 for (size_t vertex_index = 0; vertex_index < bl_vert_count; ++vertex_index)
202 {
203 const MVert& vert = bl_vertices[vertex_index];
204 blender_mesh->set_vertex_pose(vertex_index, pose, GVector3(vert.co[0], vert.co[1], vert.co[2]));
205 }
206
207 // Push normals.
208 if (export_normals)
209 {
210 for (size_t vertex_index = 0; vertex_index < bl_vert_count; ++vertex_index)
211 {
212 const MVert& vert = bl_vertices[vertex_index];
213 blender_mesh->set_vertex_normal_pose(vertex_index, pose, normalize(GVector3(vert.no[0], vert.no[1], vert.no[2])));
214 }
215 }
216 }
217
export_mesh_blender80(MeshObject * blender_mesh,const size_t bl_looptri_count,const uintptr_t bl_looptri_ptr,const size_t bl_loop_count,const uintptr_t bl_loops_ptr,const uintptr_t bl_polys_ptr,const uintptr_t bl_vertices_ptr,const uintptr_t bl_loops_uv_ptr,const bool export_normals,const bool export_uvs)218 void export_mesh_blender80(
219 MeshObject* blender_mesh,
220 const size_t bl_looptri_count,
221 const uintptr_t bl_looptri_ptr,
222 const size_t bl_loop_count,
223 const uintptr_t bl_loops_ptr,
224 const uintptr_t bl_polys_ptr,
225 const uintptr_t bl_vertices_ptr,
226 const uintptr_t bl_loops_uv_ptr,
227 const bool export_normals,
228 const bool export_uvs)
229 {
230 // Convert uintptr_t numbers to actual pointers.
231 const MLoopTri* bl_looptri_array = reinterpret_cast<MLoopTri*>(bl_looptri_ptr);
232 const MLoop* bl_loop_array = reinterpret_cast<MLoop*>(bl_loops_ptr);
233 const MPoly* bl_poly_array = reinterpret_cast<MPoly*>(bl_polys_ptr);
234 const MVert* bl_vert_array = reinterpret_cast<MVert*>(bl_vertices_ptr);
235 const MLoopUV* bl_loop_uv_array = reinterpret_cast<MLoopUV*>(bl_loops_uv_ptr);
236
237 // Push vertices.
238 blender_mesh->reserve_vertices(bl_loop_count);
239
240 for (size_t loop_index = 0; loop_index < bl_loop_count; ++loop_index)
241 {
242 const MLoop& bl_loop = bl_loop_array[loop_index];
243 const MVert& bl_vert = bl_vert_array[bl_loop.v];
244 blender_mesh->push_vertex(GVector3(bl_vert.co[0], bl_vert.co[1], bl_vert.co[2]));
245 }
246
247 // Push faces.
248 blender_mesh->reserve_triangles(bl_looptri_count);
249
250 for (size_t looptri_index = 0; looptri_index < bl_looptri_count; ++looptri_index)
251 {
252 const MLoopTri& bl_looptri = bl_looptri_array[looptri_index];
253 short mat_index = bl_poly_array[bl_looptri.poly].mat_nr;
254 blender_mesh->push_triangle(Triangle(bl_looptri.tri[0], bl_looptri.tri[1], bl_looptri.tri[2], mat_index));
255 }
256
257 // Push normals.
258 if (export_normals)
259 {
260 for (size_t loop_index = 0; loop_index < bl_loop_count; ++loop_index)
261 {
262 const MLoop& bl_loop = bl_loop_array[loop_index];
263 const MVert& bl_vert = bl_vert_array[bl_loop.v];
264 blender_mesh->push_vertex_normal(normalize(GVector3(bl_vert.no[0], bl_vert.no[1], bl_vert.no[2])));
265 }
266
267 for (size_t looptri_index = 0; looptri_index < bl_looptri_count; ++looptri_index)
268 {
269 const MLoopTri& bl_looptri = bl_looptri_array[looptri_index];
270 Triangle& as_tri = blender_mesh->get_triangle(looptri_index);
271 as_tri.m_n0 = bl_looptri.tri[0];
272 as_tri.m_n1 = bl_looptri.tri[1];
273 as_tri.m_n2 = bl_looptri.tri[2];
274 }
275 }
276
277 // Push UV coordinates.
278 if (export_uvs)
279 {
280 for (size_t loop_index = 0; loop_index < bl_loop_count; ++loop_index)
281 {
282 const MLoopUV& bl_loop_uv = bl_loop_uv_array[loop_index];
283 blender_mesh->push_tex_coords(GVector2(bl_loop_uv.uv[0], bl_loop_uv.uv[1]));
284 }
285
286 for (size_t looptri_index = 0; looptri_index < bl_looptri_count; ++looptri_index)
287 {
288 const MLoopTri& bl_looptri = bl_looptri_array[looptri_index];
289 Triangle& as_tri = blender_mesh->get_triangle(looptri_index);
290 as_tri.m_a0 = bl_looptri.tri[0];
291 as_tri.m_a1 = bl_looptri.tri[1];
292 as_tri.m_a2 = bl_looptri.tri[2];
293 }
294 }
295 }
296
export_mesh_blender80_pose(MeshObject * blender_mesh,const size_t pose,const uintptr_t bl_loop_ptr,const size_t bl_loop_count,const uintptr_t bl_vert_ptr,const bool export_normals)297 void export_mesh_blender80_pose(
298 MeshObject* blender_mesh,
299 const size_t pose,
300 const uintptr_t bl_loop_ptr,
301 const size_t bl_loop_count,
302 const uintptr_t bl_vert_ptr,
303 const bool export_normals)
304 {
305 // Convert uintptr_t numbers to actual pointers.
306 const MVert* bl_vert_array = reinterpret_cast<MVert*>(bl_vert_ptr);
307 const MLoop* bl_loop_array = reinterpret_cast<MLoop*>(bl_loop_ptr);
308
309 // Push vertices.
310 for (size_t loop_index = 0; loop_index < bl_loop_count; ++loop_index)
311 {
312 const MLoop& bl_loop = bl_loop_array[loop_index];
313 const MVert& bl_vert = bl_vert_array[bl_loop.v];
314 blender_mesh->set_vertex_pose(loop_index, pose, GVector3(bl_vert.co[0], bl_vert.co[1], bl_vert.co[2]));
315 }
316
317 // Push normals.
318 if (export_normals)
319 {
320 for (size_t loop_index = 0; loop_index < bl_loop_count; ++loop_index)
321 {
322 const MLoop& bl_loop = bl_loop_array[loop_index];
323 const MVert& bl_vert = bl_vert_array[bl_loop.v];
324 blender_mesh->set_vertex_normal_pose(loop_index, pose, normalize(GVector3(bl_vert.no[0], bl_vert.no[1], bl_vert.no[2])));
325 }
326 }
327 }
328
bind_blender_mesh_converter()329 void bind_blender_mesh_converter()
330 {
331 bpy::def("export_mesh_blender79", &export_mesh_blender79);
332 bpy::def("export_mesh_blender79_pose", &export_mesh_blender79_pose);
333 bpy::def("export_mesh_blender80", &export_mesh_blender80);
334 bpy::def("export_mesh_blender80_pose", &export_mesh_blender80_pose);
335 }
336