@@ -1201,6 +1201,100 @@ static void Scene_DefineMeshExt2(luxcore::detail::SceneImpl *scene, const string
12011201 Scene_DefineMeshExt1 (scene, meshName, p, vi, n, uv, cols, alphas, py::none ());
12021202}
12031203
1204+
1205+ // Helper for DefineMeshExt3
1206+ // Allocate internal data structure and copy array inside
1207+ template <
1208+ typename S, // Source
1209+ typename D, // Destination
1210+ D* (*Allocator)(unsigned int ),
1211+ size_t stride=3
1212+ >
1213+ std::tuple<std::unique_ptr<D>, u_int> dataCopy (
1214+ py::array_t <S, py::array::c_style> src,
1215+ const std::string& meshName,
1216+ const std::string& propertyName
1217+ ) {
1218+ // Remark:
1219+ // All buffers (triangles, points, normals...) are enclosed in smart pointers
1220+ // in order to guarantee that memory is released in case of exception arising
1221+ // during whole process: please keep it so.
1222+ using this_array_t = py::array_t <S, py::array::c_style>;
1223+ auto direct_src = src.template unchecked <2 >();
1224+
1225+ // Check
1226+ if (direct_src.shape (1 ) != stride) {
1227+ std::string errorMsg = std::string (" Scene.DefineMeshExt: Error - " )
1228+ + " Mesh '" + meshName + " ' / "
1229+ + " Property '" + std::string (propertyName) + " ' - "
1230+ + " Shape must be [N," + std::to_string (stride) + " ]" ;
1231+ throw std::runtime_error (errorMsg);
1232+ }
1233+
1234+ // Allocate & copy
1235+ u_int count = direct_src.shape (0 );
1236+ if (!count) return std::tuple (nullptr , 0 );
1237+ auto dest = std::unique_ptr<D>(Allocator (count));
1238+ std::memcpy (dest.get (), direct_src.data (0 , 0 ), direct_src.nbytes ());
1239+
1240+ return std::tuple (std::move (dest), count);
1241+ }
1242+
1243+
1244+
1245+ // Define Mesh from Numpy arrays
1246+ static void Scene_DefineMeshExt3 (
1247+ luxcore::detail::SceneImpl *scene,
1248+ const string &meshName,
1249+ const py::array_t <float , py::array::c_style> p,
1250+ const py::array_t <unsigned int , py::array::c_style> tri,
1251+ const py::array_t <float , py::array::c_style> n,
1252+ const py::array_t <float , py::array::c_style> uv,
1253+ const py::array_t <float , py::array::c_style> cols,
1254+ const py::array_t <float , py::array::c_style> alphas,
1255+ const py::array_t <float , py::array::c_style> transformation
1256+ ) {
1257+ // TODO Release GIL
1258+
1259+ // Points
1260+ auto [points, numPoints] = dataCopy<
1261+ float ,
1262+ luxrays::Point,
1263+ &luxcore::detail::SceneImpl::AllocVerticesBuffer
1264+ > (p, meshName, " Points" );
1265+
1266+ // Triangles
1267+ auto [triangles, numTriangles] = dataCopy<
1268+ u_int,
1269+ luxrays::Triangle,
1270+ &luxcore::detail::SceneImpl::AllocTrianglesBuffer
1271+ > (tri, meshName, " Triangles" );
1272+
1273+ // Create Mesh
1274+ auto * newMesh = new luxrays::ExtTriangleMesh (
1275+ u_int (numPoints),
1276+ u_int (numTriangles),
1277+ points.release (),
1278+ triangles.release (),
1279+ (luxrays::Normal*) nullptr , // Normals
1280+ (luxrays::UV*) nullptr , // UV
1281+ (luxrays::Spectrum*) nullptr , // Colors
1282+ (float *) nullptr // Alphas
1283+ );
1284+ newMesh->SetName (meshName);
1285+
1286+ // Apply the transformation if required
1287+ // TODO
1288+ // if (!transformation.is_none()) {
1289+ // float mat[16];
1290+ // GetMatrix4x4(transformation, mat);
1291+ // mesh->ApplyTransform(luxrays::Transform(luxrays::Matrix4x4(mat).Transpose()));
1292+ // }
1293+
1294+ // Insert mesh into the scene
1295+ scene->DefineMesh (newMesh);
1296+ }
1297+
12041298static void Scene_SetMeshVertexAOV (luxcore::detail::SceneImpl *scene, const string &meshName,
12051299 const size_t index, const py::object &data) {
12061300 vector<float > v;
@@ -2002,6 +2096,19 @@ PYBIND11_MODULE(pyluxcore, m) {
20022096 .def (" DefineMesh" , &Scene_DefineMesh2)
20032097 .def (" DefineMeshExt" , &Scene_DefineMeshExt1)
20042098 .def (" DefineMeshExt" , &Scene_DefineMeshExt2)
2099+ .def (
2100+ " DefineMeshExt" ,
2101+ &Scene_DefineMeshExt3,
2102+ " Define an extended mesh from Numpy arrays" ,
2103+ py::arg (" name" ),
2104+ py::arg (" points" ),
2105+ py::arg (" triangles" ),
2106+ py::arg (" normals" ) = py::none (),
2107+ py::arg (" uvs" ) = py::none (),
2108+ py::arg (" colors" ) = py::none (),
2109+ py::arg (" alphas" ) = py::none (),
2110+ py::arg (" transformation" ) = py::none ()
2111+ )
20052112 .def (" SetMeshVertexAOV" , &Scene_SetMeshVertexAOV)
20062113 .def (" SetMeshTriangleAOV" , &Scene_SetMeshTriangleAOV)
20072114 .def (" SetMeshAppliedTransformation" , &Scene_SetMeshAppliedTransformation)
0 commit comments