1 | |
2 | // |
3 | // This source file is part of appleseed. |
4 | // Visit http://appleseedhq.net/ for additional information and resources. |
5 | // |
6 | // This software is released under the MIT license. |
7 | // |
8 | // Copyright (c) 2012-2013 Esteban Tovagliari, Jupiter Jazz Limited |
9 | // Copyright (c) 2014-2017 Esteban Tovagliari, The appleseedhq Organization |
10 | // |
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | // of this software and associated documentation files (the "Software"), to deal |
13 | // in the Software without restriction, including without limitation the rights |
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
15 | // copies of the Software, and to permit persons to whom the Software is |
16 | // furnished to do so, subject to the following conditions: |
17 | // |
18 | // The above copyright notice and this permission notice shall be included in |
19 | // all copies or substantial portions of the Software. |
20 | // |
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
27 | // THE SOFTWARE. |
28 | // |
29 | |
30 | // appleseed.python headers. |
31 | #include "pyseed.h" // has to be first, to avoid redefinition warnings |
32 | #include "bindentitycontainers.h" |
33 | #include "dict2dict.h" |
34 | |
35 | // appleseed.renderer headers. |
36 | #include "renderer/api/object.h" |
37 | |
38 | // appleseed.foundation headers. |
39 | #include "foundation/utility/searchpaths.h" |
40 | |
41 | // Standard headers. |
42 | #include <cstddef> |
43 | #include <string> |
44 | |
45 | namespace bpy = boost::python; |
46 | using namespace foundation; |
47 | using namespace renderer; |
48 | using namespace std; |
49 | |
50 | // Work around a regression in Visual Studio 2015 Update 3. |
51 | #if defined(_MSC_VER) && _MSC_VER == 1900 |
52 | namespace boost |
53 | { |
54 | template <> MeshObject const volatile* get_pointer<MeshObject const volatile>(MeshObject const volatile* p) { return p; } |
55 | } |
56 | #endif |
57 | |
58 | namespace |
59 | { |
60 | auto_release_ptr<MeshObject> create_mesh_obj( |
61 | const string& name, |
62 | const bpy::dict& params) |
63 | { |
64 | return MeshObjectFactory::create(name.c_str(), bpy_dict_to_param_array(params)); |
65 | } |
66 | |
67 | const Triangle& get_triangle(const MeshObject* object, const size_t index) |
68 | { |
69 | return object->get_triangle(index); |
70 | } |
71 | |
72 | void set_triangle(MeshObject* object, const size_t index, const Triangle& triangle) |
73 | { |
74 | object->get_triangle(index) = triangle; |
75 | } |
76 | |
77 | bpy::list read_mesh_objects( |
78 | const bpy::list& search_paths, |
79 | const string& base_object_name, |
80 | const bpy::dict& params) |
81 | { |
82 | SearchPaths paths; |
83 | |
84 | for (bpy::ssize_t i = 0, e = bpy::len(search_paths); i < e; ++i) |
85 | { |
86 | bpy::extract<const char*> ex(search_paths[i]); |
87 | if (!ex.check()) |
88 | { |
89 | PyErr_SetString(PyExc_TypeError, "Incompatible type. Only strings." ); |
90 | bpy::throw_error_already_set(); |
91 | } |
92 | |
93 | paths.push_back(ex()); |
94 | } |
95 | |
96 | MeshObjectArray objs; |
97 | bpy::list py_objects; |
98 | |
99 | if (MeshObjectReader::read(paths, base_object_name.c_str(), bpy_dict_to_param_array(params), objs)) |
100 | { |
101 | for (size_t i = 0, e = objs.size(); i < e; ++i) |
102 | { |
103 | auto_release_ptr<MeshObject> object(objs[i]); |
104 | py_objects.append(object); |
105 | } |
106 | } |
107 | else |
108 | { |
109 | PyErr_SetString(PyExc_RuntimeError, "appleseed.MeshObjectReader failed" ); |
110 | bpy::throw_error_already_set(); |
111 | return py_objects; |
112 | } |
113 | |
114 | return py_objects; |
115 | } |
116 | |
117 | bool write_mesh_object( |
118 | const MeshObject* object, |
119 | const string& object_name, |
120 | const string& filename) |
121 | { |
122 | return MeshObjectWriter::write(*object, object_name.c_str(), filename.c_str()); |
123 | } |
124 | |
125 | auto_release_ptr<MeshObject> create_mesh_prim( |
126 | const string& name, |
127 | const bpy::dict& params) |
128 | { |
129 | return create_primitive_mesh(name.c_str(), bpy_dict_to_param_array(params)); |
130 | } |
131 | } |
132 | |
133 | void bind_mesh_object() |
134 | { |
135 | bpy::class_<Triangle>("Triangle" ) |
136 | .def(bpy::init<size_t, size_t, size_t>()) |
137 | .def(bpy::init<size_t, size_t, size_t, size_t>()) |
138 | .def(bpy::init<size_t, size_t, size_t, size_t, size_t, size_t, size_t>()) |
139 | .def(bpy::init<size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t>()) |
140 | |
141 | .def_readwrite("v0" , &Triangle::m_v0) |
142 | .def_readwrite("v1" , &Triangle::m_v1) |
143 | .def_readwrite("v2" , &Triangle::m_v2) |
144 | .def_readwrite("n0" , &Triangle::m_n0) |
145 | .def_readwrite("n1" , &Triangle::m_n1) |
146 | .def_readwrite("n2" , &Triangle::m_n2) |
147 | .def_readwrite("a0" , &Triangle::m_a0) |
148 | .def_readwrite("a1" , &Triangle::m_a1) |
149 | .def_readwrite("a2" , &Triangle::m_a2) |
150 | .def_readwrite("pa" , &Triangle::m_pa) |
151 | |
152 | .def("has_vertex_attributes" , &Triangle::has_vertex_attributes) |
153 | ; |
154 | |
155 | bpy::class_<MeshObject, auto_release_ptr<MeshObject>, bpy::bases<Object>, boost::noncopyable>("MeshObject" , bpy::no_init) |
156 | .def("__init__" , bpy::make_constructor(create_mesh_obj)) |
157 | |
158 | .def("reserve_vertices" , &MeshObject::reserve_vertices) |
159 | .def("push_vertex" , &MeshObject::push_vertex) |
160 | .def("get_vertex_count" , &MeshObject::get_vertex_count) |
161 | .def("get_vertex" , &MeshObject::get_vertex, bpy::return_value_policy<bpy::reference_existing_object>()) |
162 | |
163 | .def("reserve_vertex_normals" , &MeshObject::reserve_vertex_normals) |
164 | .def("push_vertex_normal" , &MeshObject::push_vertex_normal) |
165 | .def("get_vertex_normal_count" , &MeshObject::get_vertex_normal_count) |
166 | .def("get_vertex_normal" , &MeshObject::get_vertex_normal, bpy::return_value_policy<bpy::reference_existing_object>()) |
167 | |
168 | .def("reserve_tex_coords" , &MeshObject::reserve_tex_coords) |
169 | .def("push_tex_coords" , &MeshObject::push_tex_coords) |
170 | .def("get_tex_coords_count" , &MeshObject::get_tex_coords_count) |
171 | .def("get_tex_coords" , &MeshObject::get_tex_coords) |
172 | |
173 | .def("reserve_triangles" , &MeshObject::reserve_triangles) |
174 | .def("push_triangle" , &MeshObject::push_triangle) |
175 | .def("get_triangle_count" , &MeshObject::get_triangle_count) |
176 | .def("get_triangle" , get_triangle, bpy::return_value_policy<bpy::reference_existing_object>()) |
177 | .def("set_triangle" , set_triangle) |
178 | |
179 | .def("set_motion_segment_count" , &MeshObject::set_motion_segment_count) |
180 | .def("get_motion_segment_count" , &MeshObject::get_motion_segment_count) |
181 | |
182 | .def("set_vertex_pose" , &MeshObject::set_vertex_pose) |
183 | .def("get_vertex_pose" , &MeshObject::get_vertex_pose) |
184 | .def("clear_vertex_poses" , &MeshObject::clear_vertex_poses) |
185 | |
186 | .def("set_vertex_normal_pose" , &MeshObject::set_vertex_normal_pose) |
187 | .def("get_vertex_normal_pose" , &MeshObject::get_vertex_normal_pose) |
188 | .def("clear_vertex_normal_poses" , &MeshObject::clear_vertex_normal_poses) |
189 | |
190 | .def("set_vertex_tangent_pose" , &MeshObject::set_vertex_tangent_pose) |
191 | .def("get_vertex_tangent_pose" , &MeshObject::get_vertex_tangent_pose) |
192 | .def("clear_vertex_tangent_poses" , &MeshObject::clear_vertex_tangent_poses) |
193 | |
194 | .def("reserve_material_slots" , &MeshObject::reserve_material_slots) |
195 | .def("push_material_slot" , &MeshObject::push_material_slot) |
196 | ; |
197 | |
198 | boost::python::implicitly_convertible<auto_release_ptr<MeshObject>, auto_release_ptr<Object> >(); |
199 | |
200 | bpy::class_<MeshObjectReader>("MeshObjectReader" , bpy::no_init) |
201 | .def("read" , read_mesh_objects).staticmethod("read" ) |
202 | ; |
203 | |
204 | bpy::class_<MeshObjectWriter>("MeshObjectWriter" , bpy::no_init) |
205 | .def("write" , write_mesh_object).staticmethod("write" ) |
206 | ; |
207 | |
208 | bpy::def("compute_smooth_vertex_normals" , compute_smooth_vertex_normals); |
209 | bpy::def("compute_smooth_vertex_tangents" , compute_smooth_vertex_tangents); |
210 | bpy::def("create_primitive_mesh" , create_mesh_prim); |
211 | } |
212 | |