Blender V5.0
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
8
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_color_types.hh"
23
24#include <algorithm>
25
26using namespace Alembic::AbcGeom;
27
28namespace blender::io::alembic {
29
30AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
31 : AbcObjectReader(object, settings)
32{
33 IPoints ipoints(m_iobject, kWrapExisting);
34 m_schema = ipoints.getSchema();
36}
37
39{
40 return m_schema.valid();
41}
42
44 const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
45 const Object *const ob,
46 const char **r_err_str) const
47{
48 if (!Alembic::AbcGeom::IPoints::matches(alembic_header)) {
49 *r_err_str = RPT_(
50 "Object type mismatch, Alembic object path pointed to Points when importing, but not any "
51 "more");
52 return false;
53 }
54
55 if (ob->type != OB_POINTCLOUD) {
56 *r_err_str = RPT_("Object type mismatch, Alembic object path points to Points.");
57 return false;
58 }
59
60 return true;
61}
62
63void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
64{
65 PointCloud *pointcloud = BKE_pointcloud_add(bmain, m_data_name.c_str());
66
69 read_geometry(geometry_set, sample_sel, 0, "", 1.0f, nullptr);
70
71 PointCloud *read_pointcloud =
72 geometry_set.get_component_for_write<bke::PointCloudComponent>().release();
73
74 if (read_pointcloud != pointcloud) {
75 BKE_pointcloud_nomain_to_pointcloud(read_pointcloud, pointcloud);
76 }
77
79 m_object->data = pointcloud;
80
81 if (m_settings->always_add_cache_reader || has_animations(m_schema, m_settings)) {
83 }
84}
85
86static void read_points(const P3fArraySamplePtr positions, MutableSpan<float3> r_points)
87{
88 for (size_t i = 0; i < positions->size(); i++) {
89 copy_zup_from_yup(r_points[i], (*positions)[i].getValue());
90 }
91}
92
93static void read_points_sample(const IPointsSchema &schema,
94 const ISampleSelector &selector,
95 MutableSpan<float3> r_points)
96{
97 Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
98
99 const P3fArraySamplePtr &positions = sample.getPositions();
100 read_points(positions, r_points);
101}
102
103template<typename TOut, typename TIn> static TOut convert_abc_value(const TIn &in)
104{
105 static_assert(std::is_same_v<TIn, TOut>,
106 "convert_abc_value needs to be explicitly specialized for each pair of types");
107 return in;
108}
109
110template<> float3 convert_abc_value(const V3f &in)
111{
112 float3 out;
113 copy_zup_from_yup(out, in.getValue());
114 return out;
115}
116
118{
119 return ColorGeometry4f(in[0], in[1], in[2], 1.0f);
120}
121
122template<> float2 convert_abc_value(const V2f &in)
123{
124 return in.getValue();
125}
126
127template<typename TArrayProperty, typename TWriteValue>
128static void read_typed_property_sample(const ICompoundProperty &parent,
129 const ISampleSelector &selector,
130 const std::string &name,
131 bke::MutableAttributeAccessor &attribute_accessor)
132{
133 const TArrayProperty &array_prop = TArrayProperty(parent, name);
134 if (array_prop) {
135 using SamplePtr = typename TArrayProperty::sample_ptr_type;
136 using ValueType = typename TArrayProperty::value_type;
137
138 const SamplePtr sample_ptr = array_prop.getValue(selector);
140 attribute_accessor.lookup_or_add_for_write_span<TWriteValue>(name, bke::AttrDomain::Point);
141 MutableSpan<TWriteValue> span = writer.span;
142 for (const int64_t i : IndexRange(std::min(span.size(), int64_t(sample_ptr->size())))) {
143 ValueType value = (*sample_ptr)[i];
144 span[i] = convert_abc_value<TWriteValue>(value);
145 }
146 writer.finish();
147 }
148}
149
150static void read_point_arb_geom_params(const IPointsSchema &schema,
151 const ISampleSelector &selector,
152 bke::MutableAttributeAccessor &attribute_accessor)
153{
154 const ICompoundProperty prop = schema.getArbGeomParams();
155 if (!prop.valid()) {
156 return;
157 }
158
159 for (size_t i = 0; i < prop.getNumProperties(); i++) {
160 const PropertyHeader header = prop.getPropertyHeader(i);
161 const PropertyType property_type = header.getPropertyType();
162 if (property_type != kArrayProperty) {
163 // currently unsupported
164 continue;
165 }
166
167 const DataType data_type = header.getDataType();
168 const MetaData metadata = header.getMetaData();
169 const std::string interpretation = metadata.get("interpretation");
170 const std::string name = header.getName();
171
172 if (data_type == DataType(kFloat32POD, 3)) {
173 if (interpretation == C3fTPTraits::interpretation()) {
175 prop, selector, name, attribute_accessor);
176 }
177 else if (interpretation == N3fTPTraits::interpretation()) {
179 prop, selector, name, attribute_accessor);
180 }
181 else {
183 prop, selector, name, attribute_accessor);
184 }
185 }
186 else if (data_type == DataType(kFloat32POD, 2)) {
188 prop, selector, name, attribute_accessor);
189 }
190 else if (data_type == DataType(kFloat32POD, 1)) {
192 prop, selector, name, attribute_accessor);
193 }
194 }
195}
196
198 const Alembic::Abc::ISampleSelector &sample_sel,
199 int /*read_flag*/,
200 const char *velocity_name,
201 const float velocity_scale,
202 const char **r_err_str)
203{
204 BLI_assert(geometry_set.has_pointcloud());
205
206 IPointsSchema::Sample sample;
207 try {
208 sample = m_schema.getValue(sample_sel);
209 }
210 catch (Alembic::Util::Exception &ex) {
211 *r_err_str = RPT_("Error reading points sample; more detail on the console");
212 printf("Alembic: error reading points sample for '%s/%s' at time %f: %s\n",
213 m_iobject.getFullName().c_str(),
214 m_schema.getName().c_str(),
215 sample_sel.getRequestedTime(),
216 ex.what());
217 return;
218 }
219
220 PointCloud *existing_pointcloud = geometry_set.get_pointcloud_for_write();
221 PointCloud *pointcloud = existing_pointcloud;
222
223 const P3fArraySamplePtr &positions = sample.getPositions();
224
225 const IFloatGeomParam widths_param = m_schema.getWidthsParam();
226 FloatArraySamplePtr widths;
227
228 if (widths_param.valid()) {
229 IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(sample_sel);
230 widths = wsample.getVals();
231 }
232
233 if (pointcloud->totpoint != positions->size()) {
234 pointcloud = BKE_pointcloud_new_nomain(positions->size());
235 }
236
237 bke::MutableAttributeAccessor attribute_accessor = pointcloud->attributes_for_write();
238
239 MutableSpan<float3> point_positions = pointcloud->positions_for_write();
240 read_points_sample(m_schema, sample_sel, point_positions);
241
242 MutableSpan<float> point_radii = pointcloud->radius_for_write();
243
244 if (widths) {
245 for (const int64_t i : IndexRange(std::min(point_radii.size(), int64_t(widths->size())))) {
246 point_radii[i] = (*widths)[i] / 2.0f;
247 }
248 }
249 else {
250 point_radii.fill(0.01f);
251 }
252
253 read_point_arb_geom_params(m_schema, sample_sel, attribute_accessor);
254
255 if (velocity_name != nullptr && velocity_scale != 0.0f) {
256 V3fArraySamplePtr velocities = get_velocity_prop(m_schema, sample_sel, velocity_name);
257 if (velocities && pointcloud->totpoint == int(velocities->size())) {
258 bke::SpanAttributeWriter<float3> velocity_writer =
259 attribute_accessor.lookup_or_add_for_write_span<float3>("velocity",
261 MutableSpan<float3> point_velocity = velocity_writer.span;
262 for (const int64_t i :
263 IndexRange(std::min(point_velocity.size(), int64_t(velocities->size()))))
264 {
265 const Imath::V3f &vel_in = (*velocities)[i];
266 copy_zup_from_yup(point_velocity[i], vel_in.getValue());
267 point_velocity[i] *= velocity_scale;
268 }
269 velocity_writer.finish();
270 }
271 }
272
273 geometry_set.replace_pointcloud(pointcloud);
274}
275
276} // 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.
PointCloud * BKE_pointcloud_add(Main *bmain, const char *name)
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define RPT_(msgid)
Object is a sort of wrapper for general info.
@ OB_POINTCLOUD
PropertyType
Definition RNA_types.hh:161
long long int int64_t
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
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 in
#define out
#define printf(...)
static void read_typed_property_sample(const ICompoundProperty &parent, const ISampleSelector &selector, const std::string &name, bke::MutableAttributeAccessor &attribute_accessor)
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:69
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:84
static void read_point_arb_geom_params(const IPointsSchema &schema, const ISampleSelector &selector, bke::MutableAttributeAccessor &attribute_accessor)
static void read_points_sample(const IPointsSchema &schema, const ISampleSelector &selector, MutableSpan< float3 > r_points)
static TOut convert_abc_value(const TIn &in)
bool has_animations(Alembic::AbcGeom::IPolyMeshSchema &schema, ImportSettings *settings)
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
const char * name
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)
i
Definition text_draw.cc:230