33using Alembic::Abc::FloatArraySample;
34using Alembic::Abc::Int32ArraySample;
35using Alembic::Abc::OObject;
36using Alembic::Abc::V2fArraySample;
37using Alembic::Abc::V3fArraySample;
39using Alembic::AbcGeom::kFacevaryingScope;
40using Alembic::AbcGeom::OBoolProperty;
41using Alembic::AbcGeom::OCompoundProperty;
42using Alembic::AbcGeom::OFaceSet;
43using Alembic::AbcGeom::OFaceSetSchema;
44using Alembic::AbcGeom::ON3fGeomParam;
45using Alembic::AbcGeom::OPolyMesh;
46using Alembic::AbcGeom::OPolyMeshSchema;
47using Alembic::AbcGeom::OSubD;
48using Alembic::AbcGeom::OSubDSchema;
49using Alembic::AbcGeom::OV2fGeomParam;
50using Alembic::AbcGeom::UInt32ArraySample;
58 std::vector<int32_t> &face_verts,
59 std::vector<int32_t> &loop_counts);
61 std::vector<int32_t> &indices,
62 std::vector<int32_t> &lengths,
63 std::vector<float> &sharpnesses);
65 std::vector<int32_t> &indices,
66 std::vector<float> &sharpnesses);
83 abc_subdiv_schema_ = abc_subdiv_.getSchema();
88 abc_poly_mesh_schema_ = abc_poly_mesh_.getSchema();
90 OCompoundProperty typeContainer = abc_poly_mesh_.getSchema().getUserProperties();
91 OBoolProperty type(typeContainer,
"meshtype");
92 type.set(subsurf_modifier_ ==
nullptr);
101 return abc_poly_mesh_;
116 for (; md; md = md->
prev) {
137 Object *
object = context.object;
138 bool needsfree =
false;
142 if (mesh ==
nullptr) {
150 const bool tag_only =
false;
157 bmesh_from_mesh_params.calc_vert_normal =
true;
168 mesh = triangulated_mesh;
174 m_custom_data_config.
face_offsets = mesh->face_offsets_for_write().data();
175 m_custom_data_config.
corner_verts = mesh->corner_verts_for_write().data();
176 m_custom_data_config.
faces_num = mesh->faces_num;
177 m_custom_data_config.
totloop = mesh->corners_num;
178 m_custom_data_config.
totvert = mesh->verts_num;
183 write_subd(context, mesh);
186 write_mesh(context, mesh);
208 std::vector<Imath::V3f> points,
normals;
209 std::vector<int32_t> face_verts, loop_counts;
210 std::vector<Imath::V3f> velocities;
216 write_face_sets(context.object, mesh, abc_poly_mesh_schema_);
219 OPolyMeshSchema::Sample mesh_sample = OPolyMeshSchema::Sample(
220 V3fArraySample(points), Int32ArraySample(face_verts), Int32ArraySample(loop_counts));
222 UVSample uvs_and_indices;
225 const char *name =
get_uv_sample(uvs_and_indices, m_custom_data_config, &mesh->corner_data);
227 if (!uvs_and_indices.indices.empty() && !uvs_and_indices.uvs.empty()) {
228 OV2fGeomParam::Sample uv_sample;
229 uv_sample.setVals(V2fArraySample(uvs_and_indices.uvs));
230 uv_sample.setIndices(UInt32ArraySample(uvs_and_indices.indices));
231 uv_sample.setScope(kFacevaryingScope);
233 abc_poly_mesh_schema_.setUVSourceName(name);
234 mesh_sample.setUVs(uv_sample);
238 m_custom_data_config,
246 ON3fGeomParam::Sample normals_sample;
247 if (!normals.empty()) {
248 normals_sample.setScope(kFacevaryingScope);
249 normals_sample.setVals(V3fArraySample(normals));
252 mesh_sample.setNormals(normals_sample);
259 if (get_velocities(mesh, velocities)) {
260 mesh_sample.setVelocities(V3fArraySample(velocities));
266 abc_poly_mesh_schema_.set(mesh_sample);
268 write_arb_geo_params(mesh);
271void ABCGenericMeshWriter::write_subd(HierarchyContext &context,
Mesh *mesh)
273 std::vector<float> edge_crease_sharpness, vert_crease_sharpness;
274 std::vector<Imath::V3f> points;
275 std::vector<int32_t> face_verts, loop_counts;
276 std::vector<int32_t> edge_crease_indices, edge_crease_lengths, vert_crease_indices;
280 get_edge_creases(mesh, edge_crease_indices, edge_crease_lengths, edge_crease_sharpness);
284 write_face_sets(context.object, mesh, abc_subdiv_schema_);
287 OSubDSchema::Sample subdiv_sample = OSubDSchema::Sample(
288 V3fArraySample(points), Int32ArraySample(face_verts), Int32ArraySample(loop_counts));
295 OV2fGeomParam::Sample uv_sample;
296 uv_sample.setVals(V2fArraySample(
sample.uvs));
297 uv_sample.setIndices(UInt32ArraySample(
sample.indices));
298 uv_sample.setScope(kFacevaryingScope);
300 abc_subdiv_schema_.setUVSourceName(name);
301 subdiv_sample.setUVs(uv_sample);
305 m_custom_data_config,
314 if (!edge_crease_indices.empty()) {
315 subdiv_sample.setCreaseIndices(Int32ArraySample(edge_crease_indices));
316 subdiv_sample.setCreaseLengths(Int32ArraySample(edge_crease_lengths));
317 subdiv_sample.setCreaseSharpnesses(FloatArraySample(edge_crease_sharpness));
320 if (!vert_crease_indices.empty()) {
321 subdiv_sample.setCornerIndices(Int32ArraySample(vert_crease_indices));
322 subdiv_sample.setCornerSharpnesses(FloatArraySample(vert_crease_sharpness));
327 abc_subdiv_schema_.set(subdiv_sample);
329 write_arb_geo_params(mesh);
332template<
typename Schema>
333void ABCGenericMeshWriter::write_face_sets(
Object *
object,
Mesh *mesh, Schema &schema)
335 std::map<std::string, std::vector<int32_t>> geo_groups;
336 get_geo_groups(
object, mesh, geo_groups);
338 std::map<std::string, std::vector<int32_t>>::iterator it;
339 for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
340 OFaceSet face_set = schema.createFaceSet(it->first);
341 OFaceSetSchema::Sample samp;
342 samp.setFaces(Int32ArraySample(it->second));
343 face_set.getSchema().set(samp);
347void ABCGenericMeshWriter::write_arb_geo_params(
Mesh *mesh)
353 OCompoundProperty arb_geom_params;
355 arb_geom_params = abc_subdiv_.getSchema().getArbGeomParams();
358 arb_geom_params = abc_poly_mesh_.getSchema().getArbGeomParams();
363bool ABCGenericMeshWriter::get_velocities(
Mesh *mesh, std::vector<Imath::V3f> &vels)
371 if (velocity_layer ==
nullptr) {
375 const int totverts = mesh->verts_num;
376 const float(*mesh_velocities)[3] =
reinterpret_cast<float(*)[3]
>(velocity_layer->
data);
379 vels.resize(totverts);
381 for (
int i = 0; i < totverts; i++) {
388void ABCGenericMeshWriter::get_geo_groups(
Object *
object,
390 std::map<std::string, std::vector<int32_t>> &geo_groups)
392 const bke::AttributeAccessor attributes = mesh->attributes();
393 const VArraySpan<int> material_indices = *attributes.lookup_or_default<
int>(
396 for (
const int i : material_indices.index_range()) {
397 short mnr = material_indices[i];
407 if (geo_groups.find(name) == geo_groups.end()) {
408 std::vector<int32_t> faceArray;
409 geo_groups[name] = faceArray;
412 geo_groups[name].push_back(i);
415 if (geo_groups.empty()) {
420 std::vector<int32_t> faceArray;
422 for (
int i = 0,
e = mesh->totface_legacy; i <
e; i++) {
423 faceArray.push_back(i);
426 geo_groups[name] = faceArray;
435 points.resize(mesh->verts_num);
438 for (
int i = 0,
e = mesh->verts_num; i <
e; i++) {
444 std::vector<int32_t> &face_verts,
445 std::vector<int32_t> &loop_counts)
448 const Span<int> corner_verts = mesh->corner_verts();
452 face_verts.reserve(corner_verts.
size());
453 loop_counts.reserve(faces.size());
456 for (
const int i : faces.index_range()) {
458 loop_counts.push_back(face.size());
460 int corner = face.start() + (face.size() - 1);
461 for (
int j = 0; j < face.size(); j++, corner--) {
462 face_verts.push_back(corner_verts[corner]);
468 std::vector<int32_t> &indices,
469 std::vector<int32_t> &lengths,
470 std::vector<float> &sharpnesses)
484 for (
const int i : edges.index_range()) {
485 const float sharpness = creases[i];
487 if (sharpness != 0.0f) {
488 indices.push_back(edges[i][0]);
489 indices.push_back(edges[i][1]);
490 sharpnesses.push_back(sharpness);
494 lengths.resize(sharpnesses.size(), 2);
498 std::vector<int32_t> &indices,
499 std::vector<float> &sharpnesses)
512 const float sharpness = creases[i];
514 if (sharpness != 0.0f) {
515 indices.push_back(i);
516 sharpnesses.push_back(sharpness);
525 switch (mesh->normals_domain()) {
532 normals.resize(mesh->corners_num);
533 MutableSpan dst_normals(
reinterpret_cast<float3 *
>(normals.data()), normals.size());
538 for (const int i : range) {
540 copy_yup_from_zup(y_up, face_normals[i]);
541 dst_normals.slice(faces[i]).fill(y_up);
547 normals.resize(mesh->corners_num);
548 MutableSpan dst_normals(
reinterpret_cast<float3 *
>(normals.data()), normals.size());
552 const Span<float3> corner_normals = mesh->corner_normals();
554 for (const int i : range) {
555 const IndexRange face = faces[i];
556 for (const int i : face.index_range()) {
557 copy_yup_from_zup(dst_normals[face.last(i)], corner_normals[face[i]]);
struct CustomDataLayer * BKE_attribute_find(const AttributeOwner &owner, const char *name, eCustomDataType type, blender::bke::AttrDomain domain)
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Mesh * BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings)
BMesh * BKE_mesh_to_bmesh_ex(const Mesh *mesh, const BMeshCreateParams *create_params, const BMeshFromMeshParams *convert_params)
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
#define CLOG_INFO(clg_ref, level,...)
@ eModifierMode_DisableTemporary
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
static AttributeOwner from_id(ID *id)
constexpr int64_t size() const
constexpr IndexRange index_range() const
virtual std::string get_id_name(const ID *id) const
Alembic::Abc::OCompoundProperty abc_schema_prop_for_custom_props(T abc_schema)
uint32_t timesample_index_
bool frame_has_been_written_
Imath::Box3d bounding_box_
const ABCWriterConstructorArgs args_
virtual void update_bounding_box(Object *object)
virtual void do_write(HierarchyContext &context) override
ABCGenericMeshWriter(const ABCWriterConstructorArgs &args)
virtual Alembic::Abc::OObject get_alembic_object() const override
virtual void free_export_mesh(Mesh *mesh)
virtual bool is_supported(const HierarchyContext *context) const override
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree)=0
Alembic::Abc::OCompoundProperty abc_prop_for_custom_props() override
virtual void create_alembic_objects(const HierarchyContext *context) override
virtual bool export_as_subdivision_surface(Object *ob_eval) const
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree) override
draw_view in_light_buf[] float
static float normals[][3]
BLI_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
static void get_vert_creases(Mesh *mesh, std::vector< int32_t > &indices, std::vector< float > &sharpnesses)
static void get_edge_creases(Mesh *mesh, std::vector< int32_t > &indices, std::vector< int32_t > &lengths, std::vector< float > &sharpnesses)
const char * get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data)
void write_custom_data(const OCompoundProperty &prop, CDStreamConfig &config, CustomData *data, int data_type)
static void get_loop_normals(const Mesh *mesh, std::vector< Imath::V3f > &normals)
static void get_topology(Mesh *mesh, std::vector< int32_t > &face_verts, std::vector< int32_t > &loop_counts)
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config)
static void get_vertices(Mesh *mesh, std::vector< Imath::V3f > &points)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
enum eEvaluationMode evaluation_mode
bool visible_objects_only
struct ModifierData * prev
const ABCHierarchyIterator * hierarchy_iterator
Alembic::Abc::OObject abc_parent
const AlembicExportParams * export_params