Alembic: read velocities on Points #116749
|
@ -18,8 +18,10 @@
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
#include "BLI_math_base.h"
|
#include "BLI_math_base.h"
|
||||||
|
#include "BLI_math_geom.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BKE_attribute.hh"
|
||||||
#include "BKE_customdata.hh"
|
#include "BKE_customdata.hh"
|
||||||
#include "BKE_mesh.hh"
|
#include "BKE_mesh.hh"
|
||||||
|
|
||||||
|
@ -503,6 +505,28 @@ static void read_custom_data_uvs(const ICompoundProperty &prop,
|
||||||
read_uvs(config, cd_data, uv_scope, sample.getVals(), uvs_indices);
|
read_uvs(config, cd_data, uv_scope, sample.getVals(), uvs_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void read_velocity(const V3fArraySamplePtr &velocities,
|
||||||
|
const CDStreamConfig &config,
|
||||||
|
const float velocity_scale)
|
||||||
|
{
|
||||||
|
const int num_velocity_vectors = int(velocities->size());
|
||||||
|
if (num_velocity_vectors != config.mesh->verts_num) {
|
||||||
|
/* Files containing videogrammetry data may be malformed and export velocity data on missing
|
||||||
|
* frames (most likely by copying the last valid data). */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomDataLayer *velocity_layer = BKE_id_attribute_new(
|
||||||
|
&config.mesh->id, "velocity", CD_PROP_FLOAT3, bke::AttrDomain::Point, nullptr);
|
||||||
|
float(*velocity)[3] = (float(*)[3])velocity_layer->data;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void read_generated_coordinates(const ICompoundProperty &prop,
|
void read_generated_coordinates(const ICompoundProperty &prop,
|
||||||
const CDStreamConfig &config,
|
const CDStreamConfig &config,
|
||||||
const Alembic::Abc::ISampleSelector &iss)
|
const Alembic::Abc::ISampleSelector &iss)
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct Mesh;
|
||||||
|
|
||||||
using Alembic::Abc::ICompoundProperty;
|
using Alembic::Abc::ICompoundProperty;
|
||||||
using Alembic::Abc::OCompoundProperty;
|
using Alembic::Abc::OCompoundProperty;
|
||||||
|
using Alembic::Abc::V3fArraySamplePtr;
|
||||||
namespace blender::io::alembic {
|
namespace blender::io::alembic {
|
||||||
|
|
||||||
struct UVSample {
|
struct UVSample {
|
||||||
|
@ -90,6 +91,10 @@ const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, Custom
|
||||||
|
|
||||||
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config);
|
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config);
|
||||||
|
|
||||||
|
void read_velocity(const V3fArraySamplePtr &velocities,
|
||||||
|
const CDStreamConfig &config,
|
||||||
|
const float velocity_scale);
|
||||||
|
|
||||||
void read_generated_coordinates(const ICompoundProperty &prop,
|
void read_generated_coordinates(const ICompoundProperty &prop,
|
||||||
const CDStreamConfig &config,
|
const CDStreamConfig &config,
|
||||||
const Alembic::Abc::ISampleSelector &iss);
|
const Alembic::Abc::ISampleSelector &iss);
|
||||||
|
|
|
@ -402,63 +402,6 @@ static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type)
|
||||||
return cd_ptr;
|
return cd_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)) {
|
|
||||||
/* Header cannot be null here, as its presence is checked via has_property, so it is safe
|
|
||||||
* to dereference. */
|
|
||||||
const PropertyHeader *header = prop.getPropertyHeader(name);
|
|
||||||
if (!IV3fArrayProperty::matches(*header)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
|
|
||||||
if (velocity_prop) {
|
|
||||||
return velocity_prop.getValue(selector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (header.isArray()) {
|
|
||||||
if (header.getName() == name && IV3fArrayProperty::matches(header)) {
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const int num_velocity_vectors = int(velocities->size());
|
|
||||||
if (num_velocity_vectors != config.mesh->verts_num) {
|
|
||||||
/* Files containing videogrammetry data may be malformed and export velocity data on missing
|
|
||||||
* frames (most likely by copying the last valid data). */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomDataLayer *velocity_layer = BKE_id_attribute_new(
|
|
||||||
&config.mesh->id, "velocity", CD_PROP_FLOAT3, bke::AttrDomain::Point, nullptr);
|
|
||||||
float(*velocity)[3] = (float(*)[3])velocity_layer->data;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename SampleType>
|
template<typename SampleType>
|
||||||
static bool samples_have_same_topology(const SampleType &sample, const SampleType &ceil_sample)
|
static bool samples_have_same_topology(const SampleType &sample, const SampleType &ceil_sample)
|
||||||
{
|
{
|
||||||
|
|
|
@ -89,7 +89,8 @@ void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSel
|
||||||
|
|
||||||
void read_points_sample(const IPointsSchema &schema,
|
void read_points_sample(const IPointsSchema &schema,
|
||||||
const ISampleSelector &selector,
|
const ISampleSelector &selector,
|
||||||
CDStreamConfig &config)
|
CDStreamConfig &config,
|
||||||
|
ImportSettings *settings)
|
||||||
{
|
{
|
||||||
Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
|
Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
|
||||||
|
|
||||||
|
@ -109,13 +110,20 @@ void read_points_sample(const IPointsSchema &schema,
|
||||||
}
|
}
|
||||||
|
|
||||||
read_mverts(*config.mesh, positions, vnormals);
|
read_mverts(*config.mesh, positions, vnormals);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh *AbcPointsReader::read_mesh(Mesh *existing_mesh,
|
Mesh *AbcPointsReader::read_mesh(Mesh *existing_mesh,
|
||||||
const ISampleSelector &sample_sel,
|
const ISampleSelector &sample_sel,
|
||||||
int /*read_flag*/,
|
int /*read_flag*/,
|
||||||
const char * /*velocity_name*/,
|
const char *velocity_name,
|
||||||
const float /*velocity_scale*/,
|
const float velocity_scale,
|
||||||
const char **err_str)
|
const char **err_str)
|
||||||
{
|
{
|
||||||
IPointsSchema::Sample sample;
|
IPointsSchema::Sample sample;
|
||||||
|
@ -140,9 +148,13 @@ Mesh *AbcPointsReader::read_mesh(Mesh *existing_mesh,
|
||||||
new_mesh = BKE_mesh_new_nomain(positions->size(), 0, 0, 0);
|
new_mesh = BKE_mesh_new_nomain(positions->size(), 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImportSettings settings;
|
||||||
|
settings.velocity_name = velocity_name;
|
||||||
|
settings.velocity_scale = velocity_scale;
|
||||||
|
|
||||||
Mesh *mesh_to_export = new_mesh ? new_mesh : existing_mesh;
|
Mesh *mesh_to_export = new_mesh ? new_mesh : existing_mesh;
|
||||||
CDStreamConfig config = get_config(mesh_to_export);
|
CDStreamConfig config = get_config(mesh_to_export);
|
||||||
read_points_sample(m_schema, sample_sel, config);
|
read_points_sample(m_schema, sample_sel, config, &settings);
|
||||||
|
|
||||||
return mesh_to_export;
|
return mesh_to_export;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ class AbcPointsReader final : public AbcObjectReader {
|
||||||
|
|
||||||
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
|
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
|
||||||
const Alembic::AbcGeom::ISampleSelector &selector,
|
const Alembic::AbcGeom::ISampleSelector &selector,
|
||||||
CDStreamConfig &config);
|
CDStreamConfig &config,
|
||||||
|
ImportSettings *settings);
|
||||||
|
|
||||||
} // namespace blender::io::alembic
|
} // namespace blender::io::alembic
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
|
|
||||||
#include "PIL_time.h"
|
#include "PIL_time.h"
|
||||||
|
|
||||||
|
using Alembic::Abc::IV3fArrayProperty;
|
||||||
|
using Alembic::Abc::PropertyHeader;
|
||||||
|
using Alembic::Abc::V3fArraySamplePtr;
|
||||||
|
|
||||||
namespace blender::io::alembic {
|
namespace blender::io::alembic {
|
||||||
|
|
||||||
std::string get_id_name(const Object *const ob)
|
std::string get_id_name(const Object *const ob)
|
||||||
|
@ -114,6 +118,41 @@ bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string
|
||||||
return prop.getPropertyHeader(name) != nullptr;
|
return prop.getPropertyHeader(name) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema,
|
||||||
|
const Alembic::AbcGeom::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)) {
|
||||||
|
/* Header cannot be null here, as its presence is checked via has_property, so it is safe
|
||||||
|
* to dereference. */
|
||||||
|
const PropertyHeader *header = prop.getPropertyHeader(name);
|
||||||
|
if (!IV3fArrayProperty::matches(*header)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
|
||||||
|
if (velocity_prop) {
|
||||||
|
return velocity_prop.getValue(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (header.isArray()) {
|
||||||
|
if (header.getName() == name && IV3fArrayProperty::matches(header)) {
|
||||||
|
const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
|
||||||
|
return velocity_prop.getValue(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V3fArraySamplePtr();
|
||||||
|
}
|
||||||
|
|
||||||
using index_time_pair_t = std::pair<Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t>;
|
using index_time_pair_t = std::pair<Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t>;
|
||||||
|
|
||||||
std::optional<SampleInterpolationSettings> get_sample_interpolation_settings(
|
std::optional<SampleInterpolationSettings> get_sample_interpolation_settings(
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
using Alembic::Abc::chrono_t;
|
using Alembic::Abc::chrono_t;
|
||||||
|
using Alembic::Abc::V3fArraySamplePtr;
|
||||||
|
|
||||||
struct ID;
|
struct ID;
|
||||||
struct Object;
|
struct Object;
|
||||||
|
@ -82,6 +83,9 @@ void get_min_max_time(const Alembic::AbcGeom::IObject &object,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name);
|
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name);
|
||||||
|
V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema,
|
||||||
|
const Alembic::AbcGeom::ISampleSelector &selector,
|
||||||
|
const std::string &name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SampleInterpolationSettings struct holds information for interpolating data between two
|
* The SampleInterpolationSettings struct holds information for interpolating data between two
|
||||||
|
|
Loading…
Reference in New Issue