Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/io/alembic/exporter/abc_writer_mesh.cc')
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.cc578
1 files changed, 276 insertions, 302 deletions
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
index 512768bcd98..07196f2b81f 100644
--- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
@@ -19,29 +19,37 @@
*/
#include "abc_writer_mesh.h"
-#include "abc_writer_transform.h"
+#include "abc_hierarchy_iterator.h"
#include "intern/abc_axis_conversion.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim_types.h"
+#include "BLI_assert.h"
+#include "BLI_math_vector.h"
-#include "BKE_anim_data.h"
-#include "BKE_key.h"
+#include "BKE_customdata.h"
#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "bmesh.h"
#include "bmesh_tools.h"
-#include "DEG_depsgraph_query.h"
+#include "DEG_depsgraph.h"
+
+#include "DNA_layer_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_particle_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
using Alembic::Abc::FloatArraySample;
using Alembic::Abc::Int32ArraySample;
+using Alembic::Abc::OObject;
using Alembic::Abc::V2fArraySample;
using Alembic::Abc::V3fArraySample;
@@ -64,136 +72,77 @@ namespace alembic {
/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
-static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
-{
- points.clear();
- points.resize(mesh->totvert);
-
- MVert *verts = mesh->mvert;
-
- for (int i = 0, e = mesh->totvert; i < e; i++) {
- copy_yup_from_zup(points[i].getValue(), verts[i].co);
- }
-}
-
+static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points);
static void get_topology(struct Mesh *mesh,
std::vector<int32_t> &poly_verts,
std::vector<int32_t> &loop_counts,
- bool &r_has_flat_shaded_poly)
-{
- const int num_poly = mesh->totpoly;
- const int num_loops = mesh->totloop;
- MLoop *mloop = mesh->mloop;
- MPoly *mpoly = mesh->mpoly;
- r_has_flat_shaded_poly = false;
-
- poly_verts.clear();
- loop_counts.clear();
- poly_verts.reserve(num_loops);
- loop_counts.reserve(num_poly);
-
- /* NOTE: data needs to be written in the reverse order. */
- for (int i = 0; i < num_poly; i++) {
- MPoly &poly = mpoly[i];
- loop_counts.push_back(poly.totloop);
-
- r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
-
- MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
-
- for (int j = 0; j < poly.totloop; j++, loop--) {
- poly_verts.push_back(loop->v);
- }
- }
-}
-
+ bool &r_has_flat_shaded_poly);
static void get_creases(struct Mesh *mesh,
std::vector<int32_t> &indices,
std::vector<int32_t> &lengths,
- std::vector<float> &sharpnesses)
-{
- const float factor = 1.0f / 255.0f;
+ std::vector<float> &sharpnesses);
+static void get_loop_normals(struct Mesh *mesh,
+ std::vector<Imath::V3f> &normals,
+ bool has_flat_shaded_poly);
- indices.clear();
- lengths.clear();
- sharpnesses.clear();
+ABCGenericMeshWriter::ABCGenericMeshWriter(const ABCWriterConstructorArgs &args)
+ : ABCAbstractWriter(args), is_subd_(false)
+{
+}
- MEdge *edge = mesh->medge;
+void ABCGenericMeshWriter::create_alembic_objects(const HierarchyContext *context)
+{
+ if (!args_.export_params->apply_subdiv && export_as_subdivision_surface(context->object)) {
+ is_subd_ = args_.export_params->use_subdiv_schema;
+ }
- for (int i = 0, e = mesh->totedge; i < e; i++) {
- const float sharpness = static_cast<float>(edge[i].crease) * factor;
+ if (is_subd_) {
+ CLOG_INFO(&LOG, 2, "exporting OSubD %s", args_.abc_path.c_str());
+ abc_subdiv_ = OSubD(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_subdiv_schema_ = abc_subdiv_.getSchema();
+ }
+ else {
+ CLOG_INFO(&LOG, 2, "exporting OPolyMesh %s", args_.abc_path.c_str());
+ abc_poly_mesh_ = OPolyMesh(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_poly_mesh_schema_ = abc_poly_mesh_.getSchema();
- if (sharpness != 0.0f) {
- indices.push_back(edge[i].v1);
- indices.push_back(edge[i].v2);
- sharpnesses.push_back(sharpness);
- }
+ OCompoundProperty typeContainer = abc_poly_mesh_.getSchema().getUserProperties();
+ OBoolProperty type(typeContainer, "meshtype");
+ type.set(subsurf_modifier_ == nullptr);
}
- lengths.resize(sharpnesses.size(), 2);
+ Scene *scene_eval = DEG_get_evaluated_scene(args_.depsgraph);
+ liquid_sim_modifier_ = get_liquid_sim_modifier(scene_eval, context->object);
}
-static void get_loop_normals(struct Mesh *mesh,
- std::vector<Imath::V3f> &normals,
- bool has_flat_shaded_poly)
+ABCGenericMeshWriter::~ABCGenericMeshWriter()
{
- normals.clear();
-
- /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export
- * normals at all. This is also done by other software, see T71246. */
- if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) &&
- (mesh->flag & ME_AUTOSMOOTH) == 0) {
- return;
- }
-
- BKE_mesh_calc_normals_split(mesh);
- const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
- BLI_assert(lnors != NULL || !"BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
-
- normals.resize(mesh->totloop);
+}
- /* NOTE: data needs to be written in the reverse order. */
- int abc_index = 0;
- MPoly *mp = mesh->mpoly;
- for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) {
- for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) {
- int blender_index = mp->loopstart + j;
- copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]);
- }
+const Alembic::Abc::OObject ABCGenericMeshWriter::get_alembic_object() const
+{
+ if (is_subd_) {
+ return abc_subdiv_;
}
+ return abc_poly_mesh_;
}
-/* *************** Modifiers *************** */
-
-/* check if the mesh is a subsurf, ignoring disabled modifiers and
- * displace if it's after subsurf. */
-static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob)
+bool ABCGenericMeshWriter::export_as_subdivision_surface(Object *ob_eval) const
{
- ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
+ ModifierData *md = static_cast<ModifierData *>(ob_eval->modifiers.last);
for (; md; md = md->prev) {
- if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) {
- continue;
- }
-
- if (md->type == eModifierType_Subsurf) {
- SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData *>(md);
-
- if (smd->subdivType == ME_CC_SUBSURF) {
- return md;
- }
- }
-
- /* mesh is not a subsurf. break */
- if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
- return NULL;
+ /* This modifier has been temporarily disabled by SubdivModifierDisabler,
+ * so this indicates this is to be exported as subdivision surface. */
+ if (md->type == eModifierType_Subsurf && (md->mode & eModifierMode_DisableTemporary)) {
+ return true;
}
}
- return NULL;
+ return false;
}
-static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
+ModifierData *ABCGenericMeshWriter::get_liquid_sim_modifier(Scene *scene, Object *ob)
{
ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluidsim);
@@ -205,122 +154,99 @@ static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
}
}
- return NULL;
+ return nullptr;
}
-/* ************************************************************************** */
-
-AbcGenericMeshWriter::AbcGenericMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
+bool ABCGenericMeshWriter::is_supported(const HierarchyContext *context) const
{
- m_is_animated = isAnimated();
- m_subsurf_mod = NULL;
- m_is_subd = false;
-
- /* If the object is static, use the default static time sampling. */
- if (!m_is_animated) {
- time_sampling = 0;
- }
+ Object *object = context->object;
+ bool is_dupli = context->duplicator != nullptr;
+ int base_flag;
- if (!m_settings.apply_subdiv) {
- m_subsurf_mod = get_subsurf_modifier(m_settings.scene, m_object);
- m_is_subd = (m_subsurf_mod != NULL);
+ if (is_dupli) {
+ /* Construct the object's base flags from its dupli-parent, just like is done in
+ * deg_objects_dupli_iterator_next(). Without this, the visibility check below will fail. Doing
+ * this here, instead of a more suitable location in AbstractHierarchyIterator, prevents
+ * copying the Object for every dupli. */
+ base_flag = object->base_flag;
+ object->base_flag = context->duplicator->base_flag | BASE_FROM_DUPLI;
}
- m_is_liquid = (get_liquid_sim_modifier(m_settings.scene, m_object) != NULL);
+ int visibility = BKE_object_visibility(
+ object, DAG_EVAL_RENDER /* TODO(Sybren): add evaluation mode to export options? */);
- while (parent->alembicXform().getChildHeader(m_name)) {
- m_name.append("_");
+ if (is_dupli) {
+ object->base_flag = base_flag;
}
- if (m_settings.use_subdiv_schema && m_is_subd) {
- OSubD subd(parent->alembicXform(), m_name, m_time_sampling);
- m_subdiv_schema = subd.getSchema();
- }
- else {
- OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling);
- m_mesh_schema = mesh.getSchema();
-
- OCompoundProperty typeContainer = m_mesh_schema.getUserProperties();
- OBoolProperty type(typeContainer, "meshtype");
- type.set(m_is_subd);
- }
+ return (visibility & OB_VISIBLE_SELF) != 0;
}
-AbcGenericMeshWriter::~AbcGenericMeshWriter()
+void ABCGenericMeshWriter::do_write(HierarchyContext &context)
{
- if (m_subsurf_mod) {
- m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
- }
-}
+ Object *object = context.object;
+ bool needsfree = false;
-bool AbcGenericMeshWriter::isAnimated() const
-{
- if (BKE_animdata_id_is_animated(static_cast<ID *>(m_object->data))) {
- return true;
- }
- if (BKE_key_from_object(m_object) != NULL) {
- return true;
- }
+ Mesh *mesh = get_export_mesh(object, needsfree);
- /* Test modifiers. */
- ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
- while (md) {
+ if (mesh == nullptr) {
+ return;
+ }
- if (md->type != eModifierType_Subsurf) {
- return true;
- }
+ if (args_.export_params->triangulate) {
+ const bool tag_only = false;
+ const int quad_method = args_.export_params->quad_method;
+ const int ngon_method = args_.export_params->ngon_method;
- md = md->next;
- }
+ struct BMeshCreateParams bmcp = {false};
+ struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
+ BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
- return false;
-}
+ BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, nullptr, nullptr, nullptr);
-void AbcGenericMeshWriter::setIsAnimated(bool is_animated)
-{
- m_is_animated = is_animated;
-}
+ Mesh *triangulated_mesh = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
+ BM_mesh_free(bm);
-void AbcGenericMeshWriter::do_write()
-{
- /* We have already stored a sample for this object. */
- if (!m_first_frame && !m_is_animated) {
- return;
+ if (needsfree) {
+ free_export_mesh(mesh);
+ }
+ mesh = triangulated_mesh;
+ needsfree = true;
}
- bool needsfree;
- struct Mesh *mesh = getFinalMesh(needsfree);
+ m_custom_data_config.pack_uvs = args_.export_params->packuv;
+ m_custom_data_config.mpoly = mesh->mpoly;
+ m_custom_data_config.mloop = mesh->mloop;
+ m_custom_data_config.totpoly = mesh->totpoly;
+ m_custom_data_config.totloop = mesh->totloop;
+ m_custom_data_config.totvert = mesh->totvert;
try {
- if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
- writeSubD(mesh);
+ if (is_subd_) {
+ write_subd(context, mesh);
}
else {
- writeMesh(mesh);
+ write_mesh(context, mesh);
}
if (needsfree) {
- freeEvaluatedMesh(mesh);
+ free_export_mesh(mesh);
}
}
catch (...) {
if (needsfree) {
- freeEvaluatedMesh(mesh);
+ free_export_mesh(mesh);
}
throw;
}
}
-void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh)
+void ABCGenericMeshWriter::free_export_mesh(Mesh *mesh)
{
- BKE_id_free(NULL, mesh);
+ BKE_id_free(nullptr, mesh);
}
-void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
+void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
{
std::vector<Imath::V3f> points, normals;
std::vector<int32_t> poly_verts, loop_counts;
@@ -330,32 +256,33 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
get_vertices(mesh, points);
get_topology(mesh, poly_verts, loop_counts, has_flat_shaded_poly);
- if (m_first_frame && m_settings.export_face_sets) {
- writeFaceSets(mesh, m_mesh_schema);
+ if (!frame_has_been_written_ && args_.export_params->face_sets) {
+ write_face_sets(context.object, mesh, abc_poly_mesh_schema_);
}
- m_mesh_sample = OPolyMeshSchema::Sample(
+ OPolyMeshSchema::Sample mesh_sample = OPolyMeshSchema::Sample(
V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
- UVSample sample;
- if (m_settings.export_uvs) {
- const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
+ UVSample uvs_and_indices;
- if (!sample.indices.empty() && !sample.uvs.empty()) {
+ if (!frame_has_been_written_ && args_.export_params->uvs) {
+ const char *name = get_uv_sample(uvs_and_indices, m_custom_data_config, &mesh->ldata);
+
+ if (!uvs_and_indices.indices.empty() && !uvs_and_indices.uvs.empty()) {
OV2fGeomParam::Sample uv_sample;
- uv_sample.setVals(V2fArraySample(sample.uvs));
- uv_sample.setIndices(UInt32ArraySample(sample.indices));
+ uv_sample.setVals(V2fArraySample(uvs_and_indices.uvs));
+ uv_sample.setIndices(UInt32ArraySample(uvs_and_indices.indices));
uv_sample.setScope(kFacevaryingScope);
- m_mesh_schema.setUVSourceName(name);
- m_mesh_sample.setUVs(uv_sample);
+ abc_poly_mesh_schema_.setUVSourceName(name);
+ mesh_sample.setUVs(uv_sample);
}
write_custom_data(
- m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
+ abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
}
- if (m_settings.export_normals) {
+ if (args_.export_params->normals) {
get_loop_normals(mesh, normals, has_flat_shaded_poly);
ON3fGeomParam::Sample normals_sample;
@@ -364,22 +291,23 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
normals_sample.setVals(V3fArraySample(normals));
}
- m_mesh_sample.setNormals(normals_sample);
+ mesh_sample.setNormals(normals_sample);
}
- if (m_is_liquid) {
- getVelocities(mesh, velocities);
- m_mesh_sample.setVelocities(V3fArraySample(velocities));
+ if (liquid_sim_modifier_ != nullptr) {
+ get_velocities(mesh, velocities);
+ mesh_sample.setVelocities(V3fArraySample(velocities));
}
- m_mesh_sample.setSelfBounds(bounds());
+ update_bounding_box(context.object);
+ mesh_sample.setSelfBounds(bounding_box_);
- m_mesh_schema.set(m_mesh_sample);
+ abc_poly_mesh_schema_.set(mesh_sample);
- writeArbGeoParams(mesh);
+ write_arb_geo_params(mesh);
}
-void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
+void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *mesh)
{
std::vector<float> crease_sharpness;
std::vector<Imath::V3f> points;
@@ -391,15 +319,15 @@ void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
get_topology(mesh, poly_verts, loop_counts, has_flat_poly);
get_creases(mesh, crease_indices, crease_lengths, crease_sharpness);
- if (m_first_frame && m_settings.export_face_sets) {
- writeFaceSets(mesh, m_subdiv_schema);
+ if (!frame_has_been_written_ && args_.export_params->face_sets) {
+ write_face_sets(context.object, mesh, abc_subdiv_schema_);
}
- m_subdiv_sample = OSubDSchema::Sample(
+ OSubDSchema::Sample subdiv_sample = OSubDSchema::Sample(
V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
UVSample sample;
- if (m_first_frame && m_settings.export_uvs) {
+ if (!frame_has_been_written_ && args_.export_params->uvs) {
const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
if (!sample.indices.empty() && !sample.uvs.empty()) {
@@ -408,30 +336,32 @@ void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
uv_sample.setIndices(UInt32ArraySample(sample.indices));
uv_sample.setScope(kFacevaryingScope);
- m_subdiv_schema.setUVSourceName(name);
- m_subdiv_sample.setUVs(uv_sample);
+ abc_subdiv_schema_.setUVSourceName(name);
+ subdiv_sample.setUVs(uv_sample);
}
write_custom_data(
- m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
+ abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
}
if (!crease_indices.empty()) {
- m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
- m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
- m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
+ subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
+ subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
+ subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
}
- m_subdiv_sample.setSelfBounds(bounds());
- m_subdiv_schema.set(m_subdiv_sample);
+ update_bounding_box(context.object);
+ subdiv_sample.setSelfBounds(bounding_box_);
+ abc_subdiv_schema_.set(subdiv_sample);
- writeArbGeoParams(mesh);
+ write_arb_geo_params(mesh);
}
-template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *me, Schema &schema)
+template<typename Schema>
+void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Schema &schema)
{
std::map<std::string, std::vector<int32_t>> geo_groups;
- getGeoGroups(me, geo_groups);
+ get_geo_groups(object, mesh, geo_groups);
std::map<std::string, std::vector<int32_t>>::iterator it;
for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
@@ -442,83 +372,35 @@ template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *
}
}
-Mesh *AbcGenericMeshWriter::getFinalMesh(bool &r_needsfree)
+void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
{
- /* We don't want subdivided mesh data */
- if (m_subsurf_mod) {
- m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
- }
-
- r_needsfree = false;
-
- Scene *scene = DEG_get_evaluated_scene(m_settings.depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(m_settings.depsgraph, m_object);
- struct Mesh *mesh = getEvaluatedMesh(scene, ob_eval, r_needsfree);
-
- if (m_subsurf_mod) {
- m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
- }
-
- if (m_settings.triangulate) {
- const bool tag_only = false;
- const int quad_method = m_settings.quad_method;
- const int ngon_method = m_settings.ngon_method;
-
- struct BMeshCreateParams bmcp = {false};
- struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
- BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
-
- BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, NULL, NULL, NULL);
-
- Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
- BM_mesh_free(bm);
-
- if (r_needsfree) {
- BKE_id_free(NULL, mesh);
- }
-
- mesh = result;
- r_needsfree = true;
+ if (liquid_sim_modifier_ != nullptr) {
+ /* We don't need anything more for liquid meshes. */
+ return;
}
- m_custom_data_config.pack_uvs = m_settings.pack_uv;
- m_custom_data_config.mpoly = mesh->mpoly;
- m_custom_data_config.mloop = mesh->mloop;
- m_custom_data_config.totpoly = mesh->totpoly;
- m_custom_data_config.totloop = mesh->totloop;
- m_custom_data_config.totvert = mesh->totvert;
-
- return mesh;
-}
-
-void AbcGenericMeshWriter::writeArbGeoParams(struct Mesh *me)
-{
- if (m_is_liquid) {
- /* We don't need anything more for liquid meshes. */
+ if (frame_has_been_written_ || !args_.export_params->vcolors) {
return;
}
- if (m_first_frame && m_settings.export_vcols) {
- if (m_subdiv_schema.valid()) {
- write_custom_data(
- m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
- }
- else {
- write_custom_data(
- m_mesh_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
- }
+ OCompoundProperty arb_geom_params;
+ if (is_subd_) {
+ arb_geom_params = abc_subdiv_.getSchema().getArbGeomParams();
+ }
+ else {
+ arb_geom_params = abc_poly_mesh_.getSchema().getArbGeomParams();
}
+ write_custom_data(arb_geom_params, m_custom_data_config, &me->ldata, CD_MLOOPCOL);
}
-void AbcGenericMeshWriter::getVelocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
+void ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
{
const int totverts = mesh->totvert;
vels.clear();
vels.resize(totverts);
- ModifierData *md = get_liquid_sim_modifier(m_settings.scene, m_object);
- FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md);
+ FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(liquid_sim_modifier_);
FluidsimSettings *fss = fmd->fss;
if (fss->meshVelocities) {
@@ -534,8 +416,9 @@ void AbcGenericMeshWriter::getVelocities(struct Mesh *mesh, std::vector<Imath::V
}
}
-void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
- std::map<std::string, std::vector<int32_t>> &geo_groups)
+void ABCGenericMeshWriter::get_geo_groups(Object *object,
+ struct Mesh *mesh,
+ std::map<std::string, std::vector<int32_t>> &geo_groups)
{
const int num_poly = mesh->totpoly;
MPoly *polygons = mesh->mpoly;
@@ -544,13 +427,13 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
MPoly &current_poly = polygons[i];
short mnr = current_poly.mat_nr;
- Material *mat = BKE_object_material_get(m_object, mnr + 1);
+ Material *mat = BKE_object_material_get(object, mnr + 1);
if (!mat) {
continue;
}
- std::string name = get_id_name(&mat->id);
+ std::string name = args_.hierarchy_iterator->get_id_name(&mat->id);
if (geo_groups.find(name) == geo_groups.end()) {
std::vector<int32_t> faceArray;
@@ -561,9 +444,9 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
}
if (geo_groups.size() == 0) {
- Material *mat = BKE_object_material_get(m_object, 1);
+ Material *mat = BKE_object_material_get(object, 1);
- std::string name = (mat) ? get_id_name(&mat->id) : "default";
+ std::string name = (mat) ? args_.hierarchy_iterator->get_id_name(&mat->id) : "default";
std::vector<int32_t> faceArray;
@@ -575,23 +458,114 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
}
}
-AbcMeshWriter::AbcMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
+/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
+
+static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
+{
+ points.clear();
+ points.resize(mesh->totvert);
+
+ MVert *verts = mesh->mvert;
+
+ for (int i = 0, e = mesh->totvert; i < e; i++) {
+ copy_yup_from_zup(points[i].getValue(), verts[i].co);
+ }
+}
+
+static void get_topology(struct Mesh *mesh,
+ std::vector<int32_t> &poly_verts,
+ std::vector<int32_t> &loop_counts,
+ bool &r_has_flat_shaded_poly)
+{
+ const int num_poly = mesh->totpoly;
+ const int num_loops = mesh->totloop;
+ MLoop *mloop = mesh->mloop;
+ MPoly *mpoly = mesh->mpoly;
+ r_has_flat_shaded_poly = false;
+
+ poly_verts.clear();
+ loop_counts.clear();
+ poly_verts.reserve(num_loops);
+ loop_counts.reserve(num_poly);
+
+ /* NOTE: data needs to be written in the reverse order. */
+ for (int i = 0; i < num_poly; i++) {
+ MPoly &poly = mpoly[i];
+ loop_counts.push_back(poly.totloop);
+
+ r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
+
+ MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
+
+ for (int j = 0; j < poly.totloop; j++, loop--) {
+ poly_verts.push_back(loop->v);
+ }
+ }
+}
+
+static void get_creases(struct Mesh *mesh,
+ std::vector<int32_t> &indices,
+ std::vector<int32_t> &lengths,
+ std::vector<float> &sharpnesses)
+{
+ const float factor = 1.0f / 255.0f;
+
+ indices.clear();
+ lengths.clear();
+ sharpnesses.clear();
+
+ MEdge *edge = mesh->medge;
+
+ for (int i = 0, e = mesh->totedge; i < e; i++) {
+ const float sharpness = static_cast<float>(edge[i].crease) * factor;
+
+ if (sharpness != 0.0f) {
+ indices.push_back(edge[i].v1);
+ indices.push_back(edge[i].v2);
+ sharpnesses.push_back(sharpness);
+ }
+ }
+
+ lengths.resize(sharpnesses.size(), 2);
+}
+
+static void get_loop_normals(struct Mesh *mesh,
+ std::vector<Imath::V3f> &normals,
+ bool has_flat_shaded_poly)
{
+ normals.clear();
+
+ /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export
+ * normals at all. This is also done by other software, see T71246. */
+ if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) &&
+ (mesh->flag & ME_AUTOSMOOTH) == 0) {
+ return;
+ }
+
+ BKE_mesh_calc_normals_split(mesh);
+ const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
+ BLI_assert(lnors != nullptr || !"BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
+
+ normals.resize(mesh->totloop);
+
+ /* NOTE: data needs to be written in the reverse order. */
+ int abc_index = 0;
+ MPoly *mp = mesh->mpoly;
+ for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) {
+ for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) {
+ int blender_index = mp->loopstart + j;
+ copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]);
+ }
+ }
}
-AbcMeshWriter::~AbcMeshWriter()
+ABCMeshWriter::ABCMeshWriter(const ABCWriterConstructorArgs &args) : ABCGenericMeshWriter(args)
{
}
-Mesh *AbcMeshWriter::getEvaluatedMesh(Scene *scene_eval,
- Object *ob_eval,
- bool &UNUSED(r_needsfree))
+Mesh *ABCMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/)
{
- return mesh_get_eval_final(m_settings.depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
+ return BKE_object_get_evaluated_mesh(object_eval);
}
} // namespace alembic