Blender V4.3
abc_reader_points.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Kévin Dietrich. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "abc_reader_points.h"
10#include "abc_axis_conversion.h"
11#include "abc_util.h"
12
13#include "DNA_object_types.h"
15
16#include "BLT_translation.hh"
17
18#include "BKE_geometry_set.hh"
19#include "BKE_object.hh"
20#include "BKE_pointcloud.hh"
21
22#include "BLI_math_vector.h"
23
24using namespace Alembic::AbcGeom;
25
26namespace blender::io::alembic {
27
28AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
29 : AbcObjectReader(object, settings)
30{
31 IPoints ipoints(m_iobject, kWrapExisting);
32 m_schema = ipoints.getSchema();
34}
35
37{
38 return m_schema.valid();
39}
40
42 const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
43 const Object *const ob,
44 const char **r_err_str) const
45{
46 if (!Alembic::AbcGeom::IPoints::matches(alembic_header)) {
47 *r_err_str = RPT_(
48 "Object type mismatch, Alembic object path pointed to Points when importing, but not any "
49 "more");
50 return false;
51 }
52
53 if (ob->type != OB_POINTCLOUD) {
54 *r_err_str = RPT_("Object type mismatch, Alembic object path points to Points.");
55 return false;
56 }
57
58 return true;
59}
60
61void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
62{
63 PointCloud *point_cloud = static_cast<PointCloud *>(
65
68 read_geometry(geometry_set, sample_sel, 0, "", 1.0f, nullptr);
69
70 PointCloud *read_point_cloud =
71 geometry_set.get_component_for_write<bke::PointCloudComponent>().release();
72
73 if (read_point_cloud != point_cloud) {
74 BKE_pointcloud_nomain_to_pointcloud(read_point_cloud, point_cloud);
75 }
76
78 m_object->data = point_cloud;
79
82 }
83}
84
85static void read_points(const P3fArraySamplePtr positions, MutableSpan<float3> r_points)
86{
87 for (size_t i = 0; i < positions->size(); i++) {
88 copy_zup_from_yup(r_points[i], (*positions)[i].getValue());
89 }
90}
91
92static N3fArraySamplePtr read_points_sample(const IPointsSchema &schema,
93 const ISampleSelector &selector,
94 MutableSpan<float3> r_points)
95{
96 Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
97
98 const P3fArraySamplePtr &positions = sample.getPositions();
99
100 ICompoundProperty prop = schema.getArbGeomParams();
101 N3fArraySamplePtr vnormals;
102
103 if (has_property(prop, "N")) {
104 const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(
105 selector.getRequestedTime());
106 const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
107
108 if (normals_prop) {
109 vnormals = normals_prop.getValue(selector);
110 }
111 }
112
113 read_points(positions, r_points);
114 return vnormals;
115}
116
118 const Alembic::Abc::ISampleSelector &sample_sel,
119 int /*read_flag*/,
120 const char *velocity_name,
121 const float velocity_scale,
122 const char **r_err_str)
123{
124 BLI_assert(geometry_set.has_pointcloud());
125
126 IPointsSchema::Sample sample;
127 try {
128 sample = m_schema.getValue(sample_sel);
129 }
130 catch (Alembic::Util::Exception &ex) {
131 *r_err_str = RPT_("Error reading points sample; more detail on the console");
132 printf("Alembic: error reading points sample for '%s/%s' at time %f: %s\n",
133 m_iobject.getFullName().c_str(),
134 m_schema.getName().c_str(),
135 sample_sel.getRequestedTime(),
136 ex.what());
137 return;
138 }
139
140 PointCloud *existing_point_cloud = geometry_set.get_pointcloud_for_write();
141 PointCloud *point_cloud = existing_point_cloud;
142
143 const P3fArraySamplePtr &positions = sample.getPositions();
144
145 const IFloatGeomParam widths_param = m_schema.getWidthsParam();
146 FloatArraySamplePtr radii;
147
148 if (widths_param.valid()) {
149 IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(sample_sel);
150 radii = wsample.getVals();
151 }
152
153 if (point_cloud->totpoint != positions->size()) {
154 point_cloud = BKE_pointcloud_new_nomain(positions->size());
155 }
156
157 bke::MutableAttributeAccessor attribute_accessor = point_cloud->attributes_for_write();
158
159 bke::SpanAttributeWriter<float3> positions_writer =
160 attribute_accessor.lookup_or_add_for_write_span<float3>("position", bke::AttrDomain::Point);
161 MutableSpan<float3> point_positions = positions_writer.span;
162 N3fArraySamplePtr normals = read_points_sample(m_schema, sample_sel, point_positions);
163 positions_writer.finish();
164
165 bke::SpanAttributeWriter<float> point_radii_writer =
166 attribute_accessor.lookup_or_add_for_write_span<float>("radius", bke::AttrDomain::Point);
167 MutableSpan<float> point_radii = point_radii_writer.span;
168
169 if (radii) {
170 for (size_t i = 0; i < radii->size(); i++) {
171 point_radii[i] = (*radii)[i];
172 }
173 }
174 else {
175 point_radii.fill(0.01f);
176 }
177 point_radii_writer.finish();
178
179 if (normals) {
180 bke::SpanAttributeWriter<float3> normals_writer =
182 MutableSpan<float3> point_normals = normals_writer.span;
183 for (size_t i = 0; i < normals->size(); i++) {
184 Imath::V3f nor_in = (*normals)[i];
185 copy_zup_from_yup(point_normals[i], nor_in.getValue());
186 }
187 normals_writer.finish();
188 }
189
190 if (velocity_name != nullptr && velocity_scale != 0.0f) {
191 V3fArraySamplePtr velocities = get_velocity_prop(m_schema, sample_sel, velocity_name);
192 if (velocities && point_cloud->totpoint == int(velocities->size())) {
193 bke::SpanAttributeWriter<float3> velocity_writer =
194 attribute_accessor.lookup_or_add_for_write_span<float3>("velocity",
196 MutableSpan<float3> point_velocity = velocity_writer.span;
197 for (size_t i = 0; i < velocities->size(); i++) {
198 const Imath::V3f &vel_in = (*velocities)[i];
199 copy_zup_from_yup(point_velocity[i], vel_in.getValue());
200 point_velocity[i] *= velocity_scale;
201 }
202 velocity_writer.finish();
203 }
204 }
205
206 geometry_set.replace_pointcloud(point_cloud);
207}
208
209} // namespace blender::io::alembic
General operations, lookup, etc. for blender objects.
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
General operations for point clouds.
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
void * BKE_pointcloud_add_default(Main *bmain, const char *name)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define RPT_(msgid)
Object is a sort of wrapper for general info.
@ OB_POINTCLOUD
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, const Object *const ob, const char **r_err_str) const override
AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
void read_geometry(bke::GeometrySet &geometry_set, const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char *velocity_name, float velocity_scale, const char **r_err_str) override
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) override
#define printf
static N3fArraySamplePtr read_points_sample(const IPointsSchema &schema, const ISampleSelector &selector, MutableSpan< float3 > r_points)
static void read_points(const P3fArraySamplePtr positions, MutableSpan< float3 > r_points)
void get_min_max_time(const Alembic::AbcGeom::IObject &object, const Schema &schema, chrono_t &min, chrono_t &max)
Definition abc_util.h:82
BLI_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema, const Alembic::AbcGeom::ISampleSelector &selector, const std::string &name)
Definition abc_util.cc:119
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
Definition abc_util.cc:110
bool has_animations(Alembic::AbcGeom::IPolyMeshSchema &schema, ImportSettings *settings)
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
PointCloud * get_pointcloud_for_write()
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)