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