WIP: USD: add velocity to USD importer #104462
|
@ -468,9 +468,8 @@ static USDPrimReader *get_usd_reader(CacheReader *reader,
|
|||
struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
||||
struct Object *ob,
|
||||
struct Mesh *existing_mesh,
|
||||
const double time,
|
||||
const char **err_str,
|
||||
const int read_flag)
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str)
|
||||
{
|
||||
USDGeomReader *usd_reader = dynamic_cast<USDGeomReader *>(get_usd_reader(reader, ob, err_str));
|
||||
|
||||
|
@ -478,7 +477,7 @@ struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return usd_reader->read_mesh(existing_mesh, time, read_flag, err_str);
|
||||
return usd_reader->read_mesh(existing_mesh, params, err_str);
|
||||
}
|
||||
|
||||
bool USD_mesh_topology_changed(CacheReader *reader,
|
||||
|
|
|
@ -162,8 +162,7 @@ void USDCurvesReader::read_curve_sample(Curve *cu, const double motionSampleTime
|
|||
}
|
||||
|
||||
Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
||||
const double motionSampleTime,
|
||||
const int /* read_flag */,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
if (!curve_prim_) {
|
||||
|
@ -176,11 +175,11 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
|||
|
||||
pxr::VtIntArray usdCounts;
|
||||
|
||||
vertexAttr.Get(&usdCounts, motionSampleTime);
|
||||
vertexAttr.Get(&usdCounts, params.motion_sample_time);
|
||||
int num_subcurves = usdCounts.size();
|
||||
|
||||
pxr::VtVec3fArray usdPoints;
|
||||
pointsAttr.Get(&usdPoints, motionSampleTime);
|
||||
pointsAttr.Get(&usdPoints, params.motion_sample_time);
|
||||
|
||||
int vertex_idx = 0;
|
||||
int curve_idx;
|
||||
|
@ -204,7 +203,7 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
|||
|
||||
if (!same_topology) {
|
||||
BKE_nurbList_free(&curve->nurb);
|
||||
read_curve_sample(curve, motionSampleTime);
|
||||
read_curve_sample(curve, params.motion_sample_time);
|
||||
}
|
||||
else {
|
||||
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
|
||||
|
|
|
@ -36,8 +36,7 @@ class USDCurvesReader : public USDGeomReader {
|
|||
void read_curve_sample(Curve *cu, double motionSampleTime);
|
||||
|
||||
Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ class USDGeomReader : public USDXformReader {
|
|||
}
|
||||
|
||||
virtual Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str) = 0;
|
||||
|
||||
virtual bool topology_changed(const Mesh * /* existing_mesh */, double /* motionSampleTime */)
|
||||
|
|
|
@ -244,8 +244,13 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
|
|||
Mesh *mesh = (Mesh *)object_->data;
|
||||
|
||||
is_initial_load_ = true;
|
||||
Mesh *read_mesh = this->read_mesh(
|
||||
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
|
||||
USDMeshReadParams params = {};
|
||||
params.motion_sample_time = motionSampleTime;
|
||||
params.read_flags = import_params_.mesh_read_flag;
|
||||
params.velocity_name = "";
|
||||
params.velocity_scale = 0.0;
|
||||
|
||||
Mesh *read_mesh = this->read_mesh(mesh, params, nullptr);
|
||||
|
||||
is_initial_load_ = false;
|
||||
if (read_mesh != mesh) {
|
||||
|
@ -272,7 +277,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
|
|||
}
|
||||
|
||||
USDXformReader::read_object_data(bmain, motionSampleTime);
|
||||
}
|
||||
} // namespace blender::io::usd
|
||||
|
||||
bool USDMeshReader::valid() const
|
||||
{
|
||||
|
@ -727,6 +732,31 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings,
|
|||
if ((settings->read_flag & MOD_MESHSEQ_READ_COLOR) != 0) {
|
||||
read_colors(mesh, motionSampleTime);
|
||||
}
|
||||
|
||||
if (!settings->velocity_name.empty() && settings->velocity_scale != 0.0f) {
|
||||
read_velocities(mesh, motionSampleTime);
|
||||
}
|
||||
}
|
||||
|
||||
void USDMeshReader::read_velocities(Mesh *mesh, double motionSampleTime)
|
||||
{
|
||||
pxr::VtVec3fArray usd_velocities;
|
||||
mesh_prim_.GetVelocitiesAttr().Get(&usd_velocities, motionSampleTime);
|
||||
|
||||
const int num_velocity_vectors = static_cast<int>(usd_velocities.size());
|
||||
if (num_velocity_vectors != mesh->totvert) {
|
||||
/* 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(
|
||||
&mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT, nullptr);
|
||||
float(*velocity)[3] = (float(*)[3])velocity_layer->data;
|
||||
|
||||
for (int vertex_idx = 0, totvert = mesh->totvert; vertex_idx < totvert; ++vertex_idx) {
|
||||
copy_v3_v3(velocity[vertex_idx], usd_velocities[vertex_idx].data());
|
||||
}
|
||||
}
|
||||
|
||||
void USDMeshReader::assign_facesets_to_material_indices(double motionSampleTime,
|
||||
|
@ -817,8 +847,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
|
|||
}
|
||||
|
||||
Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
||||
const double motionSampleTime,
|
||||
const int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
if (!mesh_prim_) {
|
||||
|
@ -835,7 +864,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
std::vector<pxr::TfToken> uv_tokens;
|
||||
|
||||
/* Currently we only handle UV primvars. */
|
||||
if (read_flag & MOD_MESHSEQ_READ_UV) {
|
||||
if (params.read_flags & MOD_MESHSEQ_READ_UV) {
|
||||
|
||||
std::vector<pxr::UsdGeomPrimvar> primvars = primvarsAPI.GetPrimvars();
|
||||
|
||||
|
@ -888,9 +917,11 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
* the topology is consistent, as in the Alembic importer. */
|
||||
|
||||
ImportSettings settings;
|
||||
settings.read_flag |= read_flag;
|
||||
settings.read_flag |= params.read_flags;
|
||||
settings.velocity_name = params.velocity_name;
|
||||
settings.velocity_scale = params.velocity_scale;
|
||||
|
||||
if (topology_changed(existing_mesh, motionSampleTime)) {
|
||||
if (topology_changed(existing_mesh, params.motion_sample_time)) {
|
||||
new_mesh = true;
|
||||
active_mesh = BKE_mesh_new_nomain_from_template(
|
||||
existing_mesh, positions_.size(), 0, 0, face_indices_.size(), face_counts_.size());
|
||||
|
@ -900,7 +931,8 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
}
|
||||
}
|
||||
|
||||
read_mesh_sample(&settings, active_mesh, motionSampleTime, new_mesh || is_initial_load_);
|
||||
read_mesh_sample(
|
||||
&settings, active_mesh, params.motion_sample_time, new_mesh || is_initial_load_);
|
||||
|
||||
if (new_mesh) {
|
||||
/* Here we assume that the number of materials doesn't change, i.e. that
|
||||
|
@ -912,7 +944,8 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<int> material_indices =
|
||||
attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
|
||||
assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
|
||||
assign_facesets_to_material_indices(
|
||||
params.motion_sample_time, material_indices.span, &mat_map);
|
||||
material_indices.finish();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ class USDMeshReader : public USDGeomReader {
|
|||
void read_object_data(Main *bmain, double motionSampleTime) override;
|
||||
|
||||
struct Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
|
||||
bool topology_changed(const Mesh *existing_mesh, double motionSampleTime) override;
|
||||
|
@ -67,6 +66,7 @@ class USDMeshReader : public USDGeomReader {
|
|||
|
||||
void read_mpolys(Mesh *mesh);
|
||||
void read_uvs(Mesh *mesh, double motionSampleTime, bool load_uvs = false);
|
||||
void read_velocities(Mesh *mesh, double motionSampleTime);
|
||||
void read_colors(Mesh *mesh, double motionSampleTime);
|
||||
void read_vertex_creases(Mesh *mesh, double motionSampleTime);
|
||||
|
||||
|
|
|
@ -165,8 +165,7 @@ void USDNurbsReader::read_curve_sample(Curve *cu, const double motionSampleTime)
|
|||
}
|
||||
|
||||
Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
||||
const double motionSampleTime,
|
||||
const int /* read_flag */,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
pxr::UsdGeomCurves curve_prim_(prim_);
|
||||
|
@ -177,11 +176,11 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
|||
|
||||
pxr::VtIntArray usdCounts;
|
||||
|
||||
vertexAttr.Get(&usdCounts, motionSampleTime);
|
||||
vertexAttr.Get(&usdCounts, params.motion_sample_time);
|
||||
int num_subcurves = usdCounts.size();
|
||||
|
||||
pxr::VtVec3fArray usdPoints;
|
||||
pointsAttr.Get(&usdPoints, motionSampleTime);
|
||||
pointsAttr.Get(&usdPoints, params.motion_sample_time);
|
||||
|
||||
int vertex_idx = 0;
|
||||
int curve_idx;
|
||||
|
@ -205,7 +204,7 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
|||
|
||||
if (!same_topology) {
|
||||
BKE_nurbList_free(&curve->nurb);
|
||||
read_curve_sample(curve, motionSampleTime);
|
||||
read_curve_sample(curve, params.motion_sample_time);
|
||||
}
|
||||
else {
|
||||
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
|
||||
|
|
|
@ -36,8 +36,7 @@ class USDNurbsReader : public USDGeomReader {
|
|||
void read_curve_sample(Curve *cu, double motionSampleTime);
|
||||
|
||||
Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ struct ImportSettings {
|
|||
/* From MeshSeqCacheModifierData.read_flag */
|
||||
int read_flag;
|
||||
|
||||
/* From CacheFile and MeshSeqCacheModifierData */
|
||||
std::string velocity_name;
|
||||
float velocity_scale;
|
||||
|
||||
bool validate_meshes;
|
||||
|
||||
CacheFile *cache_file;
|
||||
|
@ -59,6 +63,8 @@ struct ImportSettings {
|
|||
sequence_len(1),
|
||||
sequence_offset(0),
|
||||
read_flag(0),
|
||||
velocity_name(""),
|
||||
velocity_scale(1.0f),
|
||||
validate_meshes(false),
|
||||
cache_file(NULL)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,16 @@ struct USDImportParams {
|
|||
eUSDMtlNameCollisionMode mtl_name_collision_mode;
|
||||
};
|
||||
|
||||
/* This struct is in place to store the mesh sequence parameters needed when reading a data from a
|
||||
* usd file for the mesh sequence cache.
|
||||
*/
|
||||
typedef struct USDMeshReadParams {
|
||||
double motion_sample_time; /* Read USD TimeCode in frames. */
|
||||
int read_flags; /* MOD_MESHSEQ_xxx value that is set from MeshSeqCacheModifierData.read_flag. */
|
||||
const char *velocity_name; /* From CacheFile and MeshSeqCacheModifierData */
|
||||
float velocity_scale; /* From CacheFile and MeshSeqCacheModifierData */
|
||||
} USDMeshReadParams;
|
||||
|
||||
/* The USD_export takes a as_background_job parameter, and returns a boolean.
|
||||
*
|
||||
* When as_background_job=true, returns false immediately after scheduling
|
||||
|
@ -101,9 +111,8 @@ void USD_get_transform(struct CacheReader *reader, float r_mat[4][4], float time
|
|||
struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
||||
struct Object *ob,
|
||||
struct Mesh *existing_mesh,
|
||||
double time,
|
||||
const char **err_str,
|
||||
int read_flag);
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str);
|
||||
|
||||
bool USD_mesh_topology_changed(struct CacheReader *reader,
|
||||
const struct Object *ob,
|
||||
|
|
|
@ -245,12 +245,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
|||
# endif
|
||||
break;
|
||||
}
|
||||
case CACHEFILE_TYPE_USD:
|
||||
case CACHEFILE_TYPE_USD: {
|
||||
# ifdef WITH_USD
|
||||
result = USD_read_mesh(
|
||||
mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag);
|
||||
USDMeshReadParams params = {};
|
||||
params.motion_sample_time = time * FPS;
|
||||
params.read_flags = mcmd->read_flag;
|
||||
params.velocity_name = mcmd->cache_file->velocity_name;
|
||||
params.velocity_scale = mcmd->velocity_scale;
|
||||
|
||||
result = USD_read_mesh(mcmd->reader, ctx->object, mesh, params, &err_str);
|
||||
# endif
|
||||
break;
|
||||
}
|
||||
case CACHE_FILE_TYPE_INVALID:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue