Blender V4.3
io/usd/hydra/curves.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "curves.hh"
6
7#include <pxr/base/gf/vec2f.h>
8#include <pxr/imaging/hd/tokens.h>
9
10#include "BKE_attribute.hh"
11#include "BKE_curves.hh"
12#include "BKE_customdata.hh"
13#include "BKE_material.h"
14#include "BKE_particle.h"
15
17
18#include "DNA_mesh_types.h"
19#include "DNA_meshdata_types.h"
20#include "DNA_modifier_types.h"
21
23
25
26namespace usdtokens {
27static const pxr::TfToken st("st", pxr::TfToken::Immortal);
28}
29
31 const Object *object,
32 pxr::SdfPath const &prim_id)
33 : ObjectData(scene_delegate, object, prim_id)
34{
35}
36
38{
39 ID_LOGN(1, "");
40
44}
45
47{
48 ID_LOGN(1, "");
49 scene_delegate_->GetRenderIndex().InsertRprim(
50 pxr::HdPrimTypeTokens->basisCurves, scene_delegate_, prim_id);
51}
52
54{
55 ID_LOG(1, "");
56 scene_delegate_->GetRenderIndex().RemoveRprim(prim_id);
57}
58
60{
61 const Object *object = (const Object *)id;
62 pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
63 if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
64 init();
65 bits = pxr::HdChangeTracker::AllDirty;
66 }
67 if (id->recalc & ID_RECALC_SHADING) {
69 bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
70 }
71 if (id->recalc & ID_RECALC_TRANSFORM) {
73 bits |= pxr::HdChangeTracker::DirtyTransform;
74 }
75
76 if (bits == pxr::HdChangeTracker::Clean) {
77 return;
78 }
79
80 scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(prim_id, bits);
81 ID_LOGN(1, "");
82}
83
84pxr::VtValue CurvesData::get_data(pxr::TfToken const &key) const
85{
86 if (key == pxr::HdTokens->points) {
87 return pxr::VtValue(vertices_);
88 }
89 else if (key == pxr::HdTokens->widths) {
90 return pxr::VtValue(widths_);
91 }
92 else if (key == usdtokens::st) {
93 return pxr::VtValue(uvs_);
94 }
95 return pxr::VtValue();
96}
97
98pxr::SdfPath CurvesData::material_id() const
99{
100 if (!mat_data_) {
101 return pxr::SdfPath();
102 }
103 return mat_data_->prim_id;
104}
105
107{
108 if (mat_data_ && !mat_data_->prim_id.IsEmpty()) {
109 paths.add(mat_data_->prim_id);
110 }
111}
112
113pxr::HdBasisCurvesTopology CurvesData::topology() const
114{
115 return pxr::HdBasisCurvesTopology(pxr::HdTokens->linear,
116 pxr::TfToken(),
117 pxr::HdTokens->nonperiodic,
119 pxr::VtIntArray());
120}
121
122pxr::HdPrimvarDescriptorVector CurvesData::primvar_descriptors(
123 pxr::HdInterpolation interpolation) const
124{
125 pxr::HdPrimvarDescriptorVector primvars;
126 if (interpolation == pxr::HdInterpolationVertex) {
127 if (!vertices_.empty()) {
128 primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point);
129 }
130 if (!widths_.empty()) {
131 primvars.emplace_back(pxr::HdTokens->widths, interpolation, pxr::HdPrimvarRoleTokens->none);
132 }
133 }
134 else if (interpolation == pxr::HdInterpolationUniform) {
135 if (!uvs_.empty()) {
136 primvars.emplace_back(
137 usdtokens::st, interpolation, pxr::HdPrimvarRoleTokens->textureCoordinate);
138 }
139 }
140 return primvars;
141}
142
144{
145 const Object *object = (const Object *)id;
146 const Material *mat = nullptr;
147 /* TODO: Using only first material. Add support for multi-material. */
148 if (BKE_object_material_count_eval(object) > 0) {
149 mat = BKE_object_material_get_eval(const_cast<Object *>(object), 0);
150 }
152}
153
155{
156 Object *object = (Object *)id;
157 Curves *curves_id = (Curves *)object->data;
158 const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
159
160 curve_vertex_counts_.resize(curves.curves_num());
162 curves.points_by_curve(),
163 curves.curves_range(),
165
166 const Span<float3> positions = curves.positions();
167 vertices_.resize(curves.points_num());
168 MutableSpan(vertices_.data(), vertices_.size()).copy_from(positions.cast<pxr::GfVec3f>());
169
170 const VArray<float> radii = *curves.attributes().lookup_or_default<float>(
171 "radius", bke::AttrDomain::Point, 0.01f);
172 widths_.resize(curves.points_num());
173 for (const int i : curves.points_range()) {
174 widths_[i] = radii[i] * 2.0f;
175 }
176
177 const Span<float2> surface_uv_coords = curves.surface_uv_coords();
178 if (surface_uv_coords.is_empty()) {
179 uvs_.clear();
180 return;
181 }
182
183 uvs_.resize(curves.curves_num());
184 MutableSpan(uvs_.data(), uvs_.size()).copy_from(surface_uv_coords.cast<pxr::GfVec2f>());
185}
186
188 const Object *object,
189 pxr::SdfPath const &prim_id,
190 ParticleSystem *particle_system)
191 : CurvesData(scene_delegate, object, prim_id), particle_system_(particle_system)
192{
193}
194
195bool HairData::is_supported(const ParticleSystem *particle_system)
196{
197 return particle_system->part && particle_system->part->type == PART_HAIR;
198}
199
201 Object *object,
202 ParticleSystem *particle_system)
203{
204 const bool for_render = (DEG_get_mode(scene_delegate->depsgraph) == DAG_EVAL_RENDER);
205 return psys_check_enabled(object, particle_system, for_render);
206}
207
209{
210 init();
211 scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
212 prim_id, pxr::HdChangeTracker::AllDirty);
213
214 ID_LOGN(1, "");
215}
216
218{
219 transform = pxr::GfMatrix4d(1.0);
220}
221
223{
224 ParticleCacheKey **cache = particle_system_->pathcache;
225 if (cache == nullptr) {
226 return;
227 }
228 curve_vertex_counts_.clear();
229 curve_vertex_counts_.reserve(particle_system_->totpart);
230 vertices_.clear();
231 widths_.clear();
232 uvs_.clear();
233 uvs_.reserve(particle_system_->totpart);
234
235 Object *object = (Object *)id;
236 float scale = particle_system_->part->rad_scale *
237 (std::abs(object->object_to_world().ptr()[0][0]) +
238 std::abs(object->object_to_world().ptr()[1][1]) +
239 std::abs(object->object_to_world().ptr()[2][2])) /
240 3;
241 float root = scale * particle_system_->part->rad_root;
242 float tip = scale * particle_system_->part->rad_tip;
243 float shape = particle_system_->part->shape;
244
245 ParticleCacheKey *strand;
246 for (int pa_index = 0; pa_index < particle_system_->totpart; ++pa_index) {
247 strand = cache[pa_index];
248
249 int point_count = strand->segments + 1;
250 curve_vertex_counts_.push_back(point_count);
251
252 for (int point_index = 0; point_index < point_count; ++point_index, ++strand) {
253 vertices_.push_back(pxr::GfVec3f(strand->co));
254 float x = float(point_index) / (point_count - 1);
255 float radius = pow(x, pow(10.0f, -shape));
256 widths_.push_back(root + (tip - root) * radius);
257 }
258
259 if (particle_system_->part->shape_flag & PART_SHAPE_CLOSE_TIP) {
260 widths_[widths_.size() - 1] = 0.0f;
261 }
262
263 if (particle_system_->particles) {
264 ParticleData &pa = particle_system_->particles[pa_index];
265 ParticleSystemModifierData *psmd = psys_get_modifier(object, particle_system_);
267
268 float r_uv[2] = {0.0f, 0.0f};
271 {
272 const MFace *mface = static_cast<const MFace *>(
274 const MTFace *mtface = static_cast<const MTFace *>(
276
277 if (mface && mtface) {
278 mtface += num;
279 psys_interpolate_uvs(mtface, mface->v4, pa.fuv, r_uv);
280 }
281 }
282 uvs_.push_back(pxr::GfVec2f(r_uv[0], r_uv[1]));
283 }
284 }
285}
286
287} // namespace blender::io::hydra
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for materials.
int BKE_object_material_count_eval(const struct Object *ob)
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:2150
#define DMCACHE_NOTFOUND
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition particle.cc:706
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2])
#define DMCACHE_ISCHILD
#define ELEM(...)
@ DAG_EVAL_RENDER
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SHADING
Definition DNA_ID.h:1061
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ PART_SHAPE_CLOSE_TIP
@ PART_FROM_VOLUME
@ PART_FROM_FACE
@ PART_HAIR
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
constexpr bool is_empty() const
Definition BLI_span.hh:261
void available_materials(Set< pxr::SdfPath > &paths) const override
pxr::VtVec2fArray uvs_
Definition curves.hh:26
pxr::VtIntArray curve_vertex_counts_
Definition curves.hh:24
pxr::VtFloatArray widths_
Definition curves.hh:27
pxr::VtValue get_data(pxr::TfToken const &key) const override
pxr::HdBasisCurvesTopology topology() const
pxr::VtVec3fArray vertices_
Definition curves.hh:25
pxr::SdfPath material_id() const override
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const
CurvesData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id)
HairData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id, ParticleSystem *particle_system)
static bool is_supported(const ParticleSystem *particle_system)
static bool is_visible(HydraSceneDelegate *scene_delegate, Object *object, ParticleSystem *particle_system)
pxr::SdfPath prim_id
Definition id.hh:36
HydraSceneDelegate * scene_delegate_
Definition id.hh:39
MaterialData * get_or_create_material(const Material *mat)
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
draw_view in_light_buf[] float
#define ID_LOG(level, msg,...)
Definition id.hh:53
#define ID_LOGN(level, msg,...)
Definition id.hh:56
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
CurvesGeometry geometry
Definition DNA_ID.h:413
unsigned int v4
CustomData fdata_legacy
struct ParticleSystem * psys
ParticleData * particles
ParticleSettings * part
struct ParticleCacheKey ** pathcache