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_HAIR
@ PART_FROM_VOLUME
@ PART_FROM_FACE
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
bool add(const Key &key)
Definition BLI_set.hh:248
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
constexpr bool is_empty() const
Definition BLI_span.hh:261
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
IndexRange points_range() const
Span< float3 > positions() const
Span< float2 > surface_uv_coords() const
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
pxr::GfMatrix4d transform
Definition object.hh:25
MaterialData * get_or_create_material(const Material *mat)
ObjectData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id)
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
ParticleSettings * part