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:
authorBrecht Van Lommel <brecht>2021-09-09 18:22:20 +0300
committerBrecht Van Lommel <brecht@blender.org>2021-09-10 17:48:30 +0300
commit128eb6cbe928e58dfee1c64f340fd8d663134c26 (patch)
tree68c510ccb7bc3b60af06462392ec46da5baf53a6 /source/blender/io/alembic/intern
parent42215d7cb8797ba5b631b9df93d07e895c4b1dda (diff)
Modifiers: export motion blur velocity through attribute
Previously fluid simulation and Alembic modifiers had a dedicated function to query the velocity for motion blur. Now use a more generic system where those modifiers output a velocity attribute. Advantages: * Geometry and particle nodes can output velocity through the same mechanism, or read the attribute coming from earlier modifiers. * The velocity can be preserved through modifiers like subdivision surface or auto smooth. * USD and Alembic previously only output velocity from fluid simulation, now they work with velocity from other sources too. * Simplifies the code for renderers like Cycles and exporters like Alembic and USD. This breaks compatibility: * External renderers and exporters accessing these velocities through the Python API now need to use the attribute instead. * Existing modifier node setups that create an attribute named "velocity" will render differently with motion blur. Differential Revision: https://developer.blender.org/D12305
Diffstat (limited to 'source/blender/io/alembic/intern')
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.h6
-rw-r--r--source/blender/io/alembic/intern/abc_reader_curves.cc2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_curves.h4
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.cc80
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.h8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.cc2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.h10
-rw-r--r--source/blender/io/alembic/intern/alembic_capi.cc140
8 files changed, 109 insertions, 143 deletions
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h
index e9736555ead..4fba6a2f0f7 100644
--- a/source/blender/io/alembic/intern/abc_customdata.h
+++ b/source/blender/io/alembic/intern/abc_customdata.h
@@ -122,6 +122,12 @@ void read_custom_data(const std::string &iobject_full_name,
const CDStreamConfig &config,
const Alembic::Abc::ISampleSelector &iss);
+void read_velocity(const Alembic::Abc::ICompoundProperty &prop,
+ const Alembic::Abc::PropertyHeader *prop_header,
+ const Alembic::Abc::ISampleSelector &selector,
+ const CDStreamConfig &config,
+ const char *velocity_name,
+ const float velocity_scale);
typedef enum {
ABC_UV_SCOPE_NONE,
ABC_UV_SCOPE_LOOP,
diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc
index 27ee35d1b39..688ba23333a 100644
--- a/source/blender/io/alembic/intern/abc_reader_curves.cc
+++ b/source/blender/io/alembic/intern/abc_reader_curves.cc
@@ -283,6 +283,8 @@ void AbcCurveReader::read_curve_sample(Curve *cu,
Mesh *AbcCurveReader::read_mesh(Mesh *existing_mesh,
const ISampleSelector &sample_sel,
int /*read_flag*/,
+ const char * /*velocity_name*/,
+ const float /*velocity_scale*/,
const char **err_str)
{
ICurvesSchema::Sample sample;
diff --git a/source/blender/io/alembic/intern/abc_reader_curves.h b/source/blender/io/alembic/intern/abc_reader_curves.h
index 075ed5ca6a1..11b23c8a8cf 100644
--- a/source/blender/io/alembic/intern/abc_reader_curves.h
+++ b/source/blender/io/alembic/intern/abc_reader_curves.h
@@ -45,7 +45,9 @@ class AbcCurveReader : public AbcObjectReader {
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
struct Mesh *read_mesh(struct Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str);
void read_curve_sample(Curve *cu,
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc
index 77edd4908bd..dbccc8f2851 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.cc
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc
@@ -27,6 +27,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_customdata_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -36,6 +37,7 @@
#include "BLI_listbase.h"
#include "BLI_math_geom.h"
+#include "BKE_attribute.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -43,8 +45,10 @@
#include "BKE_object.h"
using Alembic::Abc::Int32ArraySamplePtr;
+using Alembic::Abc::IV3fArrayProperty;
using Alembic::Abc::P3fArraySamplePtr;
using Alembic::Abc::PropertyHeader;
+using Alembic::Abc::V3fArraySamplePtr;
using Alembic::AbcGeom::IC3fGeomParam;
using Alembic::AbcGeom::IC4fGeomParam;
@@ -420,6 +424,52 @@ static void get_weight_and_index(CDStreamConfig &config,
config.ceil_index = i1;
}
+static V3fArraySamplePtr get_velocity_prop(const ICompoundProperty &schema,
+ const ISampleSelector &selector,
+ const std::string &name)
+{
+ for (size_t i = 0; i < schema.getNumProperties(); i++) {
+ const PropertyHeader &header = schema.getPropertyHeader(i);
+
+ if (header.isCompound()) {
+ const ICompoundProperty &prop = ICompoundProperty(schema, header.getName());
+
+ if (has_property(prop, name)) {
+ const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
+ if (velocity_prop) {
+ return velocity_prop.getValue(selector);
+ }
+ }
+ }
+ else if (header.isArray()) {
+ if (header.getName() == name) {
+ const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
+ return velocity_prop.getValue(selector);
+ }
+ }
+ }
+
+ return V3fArraySamplePtr();
+}
+
+static void read_velocity(const V3fArraySamplePtr &velocities,
+ const CDStreamConfig &config,
+ const float velocity_scale)
+{
+ CustomDataLayer *velocity_layer = BKE_id_attribute_new(
+ &config.mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT, NULL);
+ float(*velocity)[3] = (float(*)[3])velocity_layer->data;
+
+ const int num_velocity_vectors = static_cast<int>(velocities->size());
+ BLI_assert(num_velocity_vectors == config.mesh->totvert);
+
+ for (int i = 0; i < num_velocity_vectors; i++) {
+ const Imath::V3f &vel_in = (*velocities)[i];
+ copy_zup_from_yup(velocity[i], vel_in.getValue());
+ mul_v3_fl(velocity[i], velocity_scale);
+ }
+}
+
static void read_mesh_sample(const std::string &iobject_full_name,
ImportSettings *settings,
const IPolyMeshSchema &schema,
@@ -458,6 +508,13 @@ static void read_mesh_sample(const std::string &iobject_full_name,
if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector);
}
+
+ if (!settings->velocity_name.empty() && settings->velocity_scale != 0.0f) {
+ V3fArraySamplePtr velocities = get_velocity_prop(schema, selector, settings->velocity_name);
+ if (velocities) {
+ read_velocity(velocities, config, settings->velocity_scale);
+ }
+ }
}
CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation)
@@ -563,7 +620,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
m_object->data = mesh;
- Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr);
+ Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr);
if (read_mesh != mesh) {
/* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */
/* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */
@@ -630,7 +687,9 @@ bool AbcMeshReader::topology_changed(Mesh *existing_mesh, const ISampleSelector
Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
const ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str)
{
IPolyMeshSchema::Sample sample;
@@ -673,6 +732,8 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
/* Only read point data when streaming meshes, unless we need to create new ones. */
ImportSettings settings;
settings.read_flag |= read_flag;
+ settings.velocity_name = velocity_name;
+ settings.velocity_scale = velocity_scale;
if (topology_changed(existing_mesh, sample_sel)) {
new_mesh = BKE_mesh_new_nomain_from_template(
@@ -829,6 +890,13 @@ static void read_subd_sample(const std::string &iobject_full_name,
if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector);
}
+
+ if (!settings->velocity_name.empty() && settings->velocity_scale != 0.0f) {
+ V3fArraySamplePtr velocities = get_velocity_prop(schema, selector, settings->velocity_name);
+ if (velocities) {
+ read_velocity(velocities, config, settings->velocity_scale);
+ }
+ }
}
/* ************************************************************************** */
@@ -876,7 +944,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
m_object->data = mesh;
- Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr);
+ Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr);
if (read_mesh != mesh) {
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true);
}
@@ -935,7 +1003,9 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
const ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str)
{
ISubDSchema::Sample sample;
@@ -962,6 +1032,8 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
ImportSettings settings;
settings.read_flag |= read_flag;
+ settings.velocity_name = velocity_name;
+ settings.velocity_scale = velocity_scale;
if (existing_mesh->totvert != positions->size()) {
new_mesh = BKE_mesh_new_nomain_from_template(
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.h b/source/blender/io/alembic/intern/abc_reader_mesh.h
index 3329b723b77..d9f89cc8085 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.h
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.h
@@ -42,7 +42,9 @@ class AbcMeshReader : public AbcObjectReader {
struct Mesh *read_mesh(struct Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str) override;
bool topology_changed(Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel) override;
@@ -73,7 +75,9 @@ class AbcSubDReader : public AbcObjectReader {
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
struct Mesh *read_mesh(struct Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str);
};
diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc
index 9a5ffd04bd1..a6d46c4b42a 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.cc
+++ b/source/blender/io/alembic/intern/abc_reader_object.cc
@@ -167,6 +167,8 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time)
struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &UNUSED(sample_sel),
int UNUSED(read_flag),
+ const char *UNUSED(velocity_name),
+ const float UNUSED(velocity_scale),
const char **UNUSED(err_str))
{
return existing_mesh;
diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h
index 89590b26b61..6e97f841a88 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.h
+++ b/source/blender/io/alembic/intern/abc_reader_object.h
@@ -50,6 +50,10 @@ struct ImportSettings {
/* From MeshSeqCacheModifierData.read_flag */
int read_flag;
+ /* From CacheFile and MeshSeqCacheModifierData */
+ std::string velocity_name;
+ float velocity_scale;
+
bool validate_meshes;
bool always_add_cache_reader;
@@ -65,6 +69,8 @@ struct ImportSettings {
sequence_len(1),
sequence_offset(0),
read_flag(0),
+ velocity_name(""),
+ velocity_scale(1.0f),
validate_meshes(false),
always_add_cache_reader(false),
cache_file(NULL)
@@ -143,7 +149,9 @@ class AbcObjectReader {
virtual struct Mesh *read_mesh(struct Mesh *mesh,
const Alembic::Abc::ISampleSelector &sample_sel,
- int read_flag,
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale,
const char **err_str);
virtual bool topology_changed(Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel);
diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc
index deb945b767c..63565b902f3 100644
--- a/source/blender/io/alembic/intern/alembic_capi.cc
+++ b/source/blender/io/alembic/intern/alembic_capi.cc
@@ -786,7 +786,9 @@ Mesh *ABC_read_mesh(CacheReader *reader,
Mesh *existing_mesh,
const float time,
const char **err_str,
- int read_flag)
+ const int read_flag,
+ const char *velocity_name,
+ const float velocity_scale)
{
AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str);
if (abc_reader == nullptr) {
@@ -794,7 +796,8 @@ Mesh *ABC_read_mesh(CacheReader *reader,
}
ISampleSelector sample_sel = sample_selector_for_time(time);
- return abc_reader->read_mesh(existing_mesh, sample_sel, read_flag, err_str);
+ return abc_reader->read_mesh(
+ existing_mesh, sample_sel, read_flag, velocity_name, velocity_scale, err_str);
}
bool ABC_mesh_topology_changed(
@@ -860,136 +863,3 @@ CacheReader *CacheReader_open_alembic_object(CacheArchiveHandle *handle,
return reinterpret_cast<CacheReader *>(abc_reader);
}
-
-/* ************************************************************************** */
-
-static const PropertyHeader *get_property_header(const IPolyMeshSchema &schema, const char *name)
-{
- const PropertyHeader *prop_header = schema.getPropertyHeader(name);
-
- if (prop_header) {
- return prop_header;
- }
-
- ICompoundProperty prop = schema.getArbGeomParams();
-
- if (!has_property(prop, name)) {
- return nullptr;
- }
-
- return prop.getPropertyHeader(name);
-}
-
-bool ABC_has_vec3_array_property_named(struct CacheReader *reader, const char *name)
-{
- AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
-
- if (!abc_reader) {
- return false;
- }
-
- IObject iobject = abc_reader->iobject();
-
- if (!iobject.valid()) {
- return false;
- }
-
- const ObjectHeader &header = iobject.getHeader();
-
- if (!IPolyMesh::matches(header)) {
- return false;
- }
-
- IPolyMesh mesh(iobject, kWrapExisting);
- IPolyMeshSchema schema = mesh.getSchema();
-
- const PropertyHeader *prop_header = get_property_header(schema, name);
-
- if (!prop_header) {
- return false;
- }
-
- return IV3fArrayProperty::matches(prop_header->getMetaData());
-}
-
-static V3fArraySamplePtr get_velocity_prop(const IPolyMeshSchema &schema,
- const ISampleSelector &iss,
- const std::string &name)
-{
- const PropertyHeader *prop_header = schema.getPropertyHeader(name);
-
- if (prop_header) {
- const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
- return velocity_prop.getValue(iss);
- }
-
- ICompoundProperty prop = schema.getArbGeomParams();
-
- if (!has_property(prop, name)) {
- return V3fArraySamplePtr();
- }
-
- const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
-
- if (velocity_prop) {
- return velocity_prop.getValue(iss);
- }
-
- return V3fArraySamplePtr();
-}
-
-int ABC_read_velocity_cache(CacheReader *reader,
- const char *velocity_name,
- const float time,
- float velocity_scale,
- int num_vertices,
- float *r_vertex_velocities)
-{
- AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
-
- if (!abc_reader) {
- return -1;
- }
-
- IObject iobject = abc_reader->iobject();
-
- if (!iobject.valid()) {
- return -1;
- }
-
- const ObjectHeader &header = iobject.getHeader();
-
- if (!IPolyMesh::matches(header)) {
- return -1;
- }
-
- IPolyMesh mesh(iobject, kWrapExisting);
- IPolyMeshSchema schema = mesh.getSchema();
- ISampleSelector sample_sel(time);
- const IPolyMeshSchema::Sample sample = schema.getValue(sample_sel);
-
- V3fArraySamplePtr velocities = get_velocity_prop(schema, sample_sel, velocity_name);
-
- if (!velocities) {
- return -1;
- }
-
- float vel[3];
-
- int num_velocity_vectors = static_cast<int>(velocities->size());
-
- if (num_velocity_vectors != num_vertices) {
- return -1;
- }
-
- for (size_t i = 0; i < velocities->size(); ++i) {
- const Imath::V3f &vel_in = (*velocities)[i];
- copy_zup_from_yup(vel, vel_in.getValue());
-
- mul_v3_fl(vel, velocity_scale);
-
- copy_v3_v3(r_vertex_velocities + i * 3, vel);
- }
-
- return num_vertices;
-}