Cleanup: Small improvements to Hydra mesh and curves export

- Use threadsafe normal computation (will be improved more in #93551)
- Copy data directly instead of loops when format is the same
- Use bke::CurvesGeometry wrapper and attribute API
- Avoid `push_back` when size is known ahead of time
This commit is contained in:
Hans Goudey
2023-08-04 13:59:22 -04:00
parent 66dd1657b8
commit e0efc234c8
3 changed files with 47 additions and 51 deletions

View File

@@ -141,45 +141,41 @@ void CurvesData::write_materials()
mat_data_ = get_or_create_material(mat);
}
void CurvesData::write_curves(const Curves *curves)
void CurvesData::write_curves(const Curves *curves_id)
{
curve_vertex_counts_.clear();
widths_.clear();
vertices_.clear();
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
const float *radii = (const float *)CustomData_get_layer_named(
&curves->geometry.point_data, CD_PROP_FLOAT, "radius");
const float(*positions)[3] = (const float(*)[3])CustomData_get_layer_named(
&curves->geometry.point_data, CD_PROP_FLOAT3, "position");
curve_vertex_counts_.resize(curves.curves_num());
offset_indices::copy_group_sizes(
curves.points_by_curve(),
curves.curves_range(),
MutableSpan(curve_vertex_counts_.data(), curve_vertex_counts_.size()));
vertices_.reserve(curves->geometry.curve_num);
const Span<float3> positions = curves.positions();
vertices_.resize(curves.points_num());
MutableSpan(vertices_.data(), vertices_.size()).copy_from(positions.cast<pxr::GfVec3f>());
for (int i = 0; i < curves->geometry.curve_num; i++) {
int first_point_index = *(curves->geometry.curve_offsets + i);
int num_points = *(curves->geometry.curve_offsets + i + 1) - first_point_index;
curve_vertex_counts_.push_back(num_points);
/* Set radius similar to Cycles if isn't set */
for (int j = 0; j < num_points; j++) {
int ind = first_point_index + j;
widths_.push_back(radii ? radii[ind] * 2 : 0.01f);
vertices_.push_back(pxr::GfVec3f(positions[ind][0], positions[ind][1], positions[ind][2]));
}
const VArray<float> radii = *curves.attributes().lookup_or_default<float>(
"radius", ATTR_DOMAIN_POINT, 0.01f);
widths_.resize(curves.points_num());
for (const int i : curves.points_range()) {
widths_[i] = radii[i] * 2.0f;
}
write_uv_maps(curves);
write_uv_maps(curves_id);
}
void CurvesData::write_uv_maps(const Curves *curves)
void CurvesData::write_uv_maps(const Curves *curves_id)
{
uvs_.clear();
const float(*uvs)[2] = (const float(*)[2])CustomData_get_layer_named(
&curves->geometry.curve_data, CD_PROP_FLOAT2, "surface_uv_coordinate");
if (uvs) {
for (int i = 0; i < curves->geometry.curve_num; i++) {
uvs_.push_back(pxr::GfVec2f(uvs[i][0], uvs[i][1]));
}
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
const Span<float2> surface_uv_coords = curves.surface_uv_coords();
if (surface_uv_coords.is_empty()) {
uvs_.clear();
return;
}
uvs_.resize(curves.curves_num());
MutableSpan(uvs_.data(), uvs_.size()).copy_from(surface_uv_coords.cast<pxr::GfVec2f>());
}
} // namespace blender::io::hydra

View File

@@ -47,8 +47,8 @@ class CurvesData : public ObjectData {
void write_materials() override;
private:
void write_curves(const Curves *curves);
void write_uv_maps(const Curves *curves);
void write_curves(const Curves *curves_id);
void write_uv_maps(const Curves *curves_id);
};
} // namespace blender::io::hydra

View File

@@ -193,7 +193,8 @@ void MeshData::write_materials()
const Object *object = (const Object *)id;
for (int i = 0; i < submeshes_.size(); ++i) {
SubMesh &m = submeshes_[i];
Material *mat = BKE_object_material_get_eval(const_cast<Object *>(object), m.mat_index + 1);
const Material *mat = BKE_object_material_get_eval(const_cast<Object *>(object),
m.mat_index + 1);
m.mat_data = get_or_create_material(mat);
}
}
@@ -231,11 +232,14 @@ void MeshData::write_submeshes(const Mesh *mesh)
const Span<int> corner_verts = mesh->corner_verts();
const Span<MLoopTri> looptris = mesh->looptris();
BKE_mesh_calc_normals_split(const_cast<Mesh *>(mesh));
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->loop_data, CD_NORMAL);
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->loop_data, CD_PROP_FLOAT2);
Array<float3> corner_normals(mesh->totloop);
BKE_mesh_calc_normals_split_ex(
mesh, nullptr, reinterpret_cast<float(*)[3]>(corner_normals.data()));
for (size_t i = 0; i < looptris.size(); ++i) {
const float2 *uv_map = static_cast<const float2 *>(
CustomData_get_layer(&mesh->loop_data, CD_PROP_FLOAT2));
for (const int i : looptris.index_range()) {
int mat_ind = material_indices ? material_indices[looptri_faces[i]] : 0;
const MLoopTri &lt = looptris[i];
SubMesh &sm = submeshes_[mat_ind];
@@ -245,16 +249,16 @@ void MeshData::write_submeshes(const Mesh *mesh)
sm.face_vertex_indices.push_back(corner_verts[lt.tri[1]]);
sm.face_vertex_indices.push_back(corner_verts[lt.tri[2]]);
if (lnors) {
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
if (!corner_normals.is_empty()) {
sm.normals.push_back(pxr::GfVec3f(&corner_normals[lt.tri[0]].x));
sm.normals.push_back(pxr::GfVec3f(&corner_normals[lt.tri[1]].x));
sm.normals.push_back(pxr::GfVec3f(&corner_normals[lt.tri[2]].x));
}
if (luvs) {
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
if (uv_map) {
sm.uvs.push_back(pxr::GfVec2f(&uv_map[lt.tri[0]].x));
sm.uvs.push_back(pxr::GfVec2f(&uv_map[lt.tri[1]].x));
sm.uvs.push_back(pxr::GfVec2f(&uv_map[lt.tri[2]].x));
}
}
@@ -272,13 +276,9 @@ void MeshData::write_submeshes(const Mesh *mesh)
return;
}
/* vertices */
const blender::Span<blender::float3> verts = mesh->vert_positions();
pxr::VtVec3fArray vertices(mesh->totvert);
int i = 0;
for (blender::float3 v : verts) {
vertices[i++] = pxr::GfVec3f(v.x, v.y, v.z);
}
const Span<float3> positions = mesh->vert_positions();
MutableSpan(vertices.data(), vertices.size()).copy_from(positions.cast<pxr::GfVec3f>());
if (submeshes_.size() == 1) {
submeshes_[0].vertices = std::move(vertices);