Blender V4.5
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 <algorithm>
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 *pointcloud = BKE_pointcloud_add(bmain, m_data_name.c_str());
64
67 read_geometry(geometry_set, sample_sel, 0, "", 1.0f, nullptr);
68
69 PointCloud *read_pointcloud =
70 geometry_set.get_component_for_write<bke::PointCloudComponent>().release();
71
72 if (read_pointcloud != pointcloud) {
73 BKE_pointcloud_nomain_to_pointcloud(read_pointcloud, pointcloud);
74 }
75
77 m_object->data = pointcloud;
78
79 if (m_settings->always_add_cache_reader || has_animations(m_schema, m_settings)) {
81 }
82}
83
84static void read_points(const P3fArraySamplePtr positions, MutableSpan<float3> r_points)
85{
86 for (size_t i = 0; i < positions->size(); i++) {
87 copy_zup_from_yup(r_points[i], (*positions)[i].getValue());
88 }
89}
90
91static N3fArraySamplePtr read_points_sample(const IPointsSchema &schema,
92 const ISampleSelector &selector,
93 MutableSpan<float3> r_points)
94{
95 Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
96
97 const P3fArraySamplePtr &positions = sample.getPositions();
98
99 ICompoundProperty prop = schema.getArbGeomParams();
100 N3fArraySamplePtr vnormals;
101
102 if (has_property(prop, "N")) {
103 const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(
104 selector.getRequestedTime());
105 const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
106
107 if (normals_prop) {
108 vnormals = normals_prop.getValue(selector);
109 }
110 }
111
112 read_points(positions, r_points);
113 return vnormals;
114}
115
117 const Alembic::Abc::ISampleSelector &sample_sel,
118 int /*read_flag*/,
119 const char *velocity_name,
120 const float velocity_scale,
121 const char **r_err_str)
122{
123 BLI_assert(geometry_set.has_pointcloud());
124
125 IPointsSchema::Sample sample;
126 try {
127 sample = m_schema.getValue(sample_sel);
128 }
129 catch (Alembic::Util::Exception &ex) {
130 *r_err_str = RPT_("Error reading points sample; more detail on the console");
131 printf("Alembic: error reading points sample for '%s/%s' at time %f: %s\n",
132 m_iobject.getFullName().c_str(),
133 m_schema.getName().c_str(),
134 sample_sel.getRequestedTime(),
135 ex.what());
136 return;
137 }
138
139 PointCloud *existing_pointcloud = geometry_set.get_pointcloud_for_write();
140 PointCloud *pointcloud = existing_pointcloud;
141
142 const P3fArraySamplePtr &positions = sample.getPositions();
143
144 const IFloatGeomParam widths_param = m_schema.getWidthsParam();
145 FloatArraySamplePtr widths;
146
147 if (widths_param.valid()) {
148 IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(sample_sel);
149 widths = wsample.getVals();
150 }
151
152 if (pointcloud->totpoint != positions->size()) {
153 pointcloud = BKE_pointcloud_new_nomain(positions->size());
154 }
155
156 bke::MutableAttributeAccessor attribute_accessor = pointcloud->attributes_for_write();
157
158 MutableSpan<float3> point_positions = pointcloud->positions_for_write();
159 N3fArraySamplePtr normals = read_points_sample(m_schema, sample_sel, point_positions);
160 MutableSpan<float> point_radii = pointcloud->radius_for_write();
161
162 if (widths) {
163 for (const int64_t i : IndexRange(std::min(point_radii.size(), int64_t(widths->size())))) {
164 point_radii[i] = (*widths)[i] / 2.0f;
165 }
166 }
167 else {
168 point_radii.fill(0.01f);
169 }
170
171 if (normals) {
172 bke::SpanAttributeWriter<float3> normals_writer =
174 MutableSpan<float3> point_normals = normals_writer.span;
175 for (const int64_t i : IndexRange(std::min(point_normals.size(), int64_t(normals->size())))) {
176 Imath::V3f nor_in = (*normals)[i];
177 copy_zup_from_yup(point_normals[i], nor_in.getValue());
178 }
179 normals_writer.finish();
180 }
181
182 if (velocity_name != nullptr && velocity_scale != 0.0f) {
183 V3fArraySamplePtr velocities = get_velocity_prop(m_schema, sample_sel, velocity_name);
184 if (velocities && pointcloud->totpoint == int(velocities->size())) {
185 bke::SpanAttributeWriter<float3> velocity_writer =
186 attribute_accessor.lookup_or_add_for_write_span<float3>("velocity",
188 MutableSpan<float3> point_velocity = velocity_writer.span;
189 for (const int64_t i :
190 IndexRange(std::min(point_velocity.size(), int64_t(velocities->size()))))
191 {
192 const Imath::V3f &vel_in = (*velocities)[i];
193 copy_zup_from_yup(point_velocity[i], vel_in.getValue());
194 point_velocity[i] *= velocity_scale;
195 }
196 velocity_writer.finish();
197 }
198 }
199
200 geometry_set.replace_pointcloud(pointcloud);
201}
202
203} // 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
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, eCustomDataType 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
static float normals[][3]
#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:81
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:120
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
Definition abc_util.cc:111
bool has_animations(Alembic::AbcGeom::IPolyMeshSchema &schema, ImportSettings *settings)
VecBase< float, 3 > float3
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