Blender V5.0
scene/pointcloud.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "bvh/bvh.h"
6
7#include "scene/pointcloud.h"
8#include "scene/scene.h"
9
11
12/* PointCloud Point */
13
15 const float *radius,
16 BoundBox &bounds) const
17{
18 bounds.grow(points[index], radius[index]);
19}
20
22 const float *radius,
23 const Transform &aligned_space,
24 BoundBox &bounds) const
25{
26 const float3 P = transform_point(&aligned_space, points[index]);
27 bounds.grow(P, radius[index]);
28}
29
31{
32 bounds.grow(make_float3(point), point.w);
33}
34
36 const float *radius,
37 const float4 *point_steps,
38 const size_t num_points,
39 const size_t num_steps,
40 const float time,
41 size_t p) const
42{
43 /* Figure out which steps we need to fetch and their
44 * interpolation factor. */
45 const size_t max_step = num_steps - 1;
46 const size_t step = min((size_t)(time * max_step), max_step - 1);
47 const float t = time * max_step - step;
48 /* Fetch vertex coordinates. */
49 const float4 curr_key = point_for_step(
50 points, radius, point_steps, num_points, num_steps, step, p);
51 const float4 next_key = point_for_step(
52 points, radius, point_steps, num_points, num_steps, step + 1, p);
53 /* Interpolate between steps. */
54 return (1.0f - t) * curr_key + t * next_key;
55}
56
58 const float *radius,
59 const float4 *point_steps,
60 const size_t num_points,
61 const size_t num_steps,
62 size_t step,
63 size_t p) const
64{
65 const size_t center_step = ((num_steps - 1) / 2);
66 if (step == center_step) {
67 /* Center step: regular key location. */
68 return make_float4(points[p], radius[p]);
69 }
70 /* Center step is not stored in this array. */
71 if (step > center_step) {
72 step--;
73 }
74 const size_t offset = step * num_points;
75 return point_steps[offset + p];
76}
77
78/* PointCloud */
79
81{
83 "pointcloud", create, NodeType::NONE, Geometry::get_node_base_type());
84
85 SOCKET_POINT_ARRAY(points, "Points", array<float3>());
86 SOCKET_FLOAT_ARRAY(radius, "Radius", array<float>());
87 SOCKET_INT_ARRAY(shader, "Shader", array<int>());
88
89 return type;
90}
91
93
94PointCloud::~PointCloud() = default;
95
96void PointCloud::resize(const int numpoints)
97{
98 points.resize(numpoints);
99 radius.resize(numpoints);
100 shader.resize(numpoints);
101 attributes.resize();
102
103 tag_points_modified();
104 tag_radius_modified();
105 tag_shader_modified();
106}
107
108void PointCloud::reserve(const int numpoints)
109{
110 points.reserve(numpoints);
111 radius.reserve(numpoints);
112 shader.reserve(numpoints);
113 attributes.resize(true);
114}
115
120
121void PointCloud::clear(const bool preserve_shaders)
122{
123 Geometry::clear(preserve_shaders);
124
125 points.clear();
126 radius.clear();
127 shader.clear();
128 attributes.clear();
129
130 tag_points_modified();
131 tag_radius_modified();
132 tag_shader_modified();
133}
134
135void PointCloud::add_point(const float3 co, const float r, const int shader_index)
136{
137 points.push_back_reserved(co);
138 radius.push_back_reserved(r);
139 shader.push_back_reserved(shader_index);
140
141 tag_points_modified();
142 tag_radius_modified();
143 tag_shader_modified();
144}
145
147{
149 if (attr_mP) {
150 float3 *points_data = points.data();
151 const size_t numpoints = points.size();
152 float *radius_data = radius.data();
153
154 float4 *attrib_P = attr_mP->data_float4() + motion_step * numpoints;
155 for (int i = 0; i < numpoints; i++) {
156 const float3 P = points_data[i];
157 const float r = radius_data[i];
158 attrib_P[i] = make_float4(P, r);
159 }
160 }
161}
162
163void PointCloud::get_uv_tiles(ustring map, unordered_set<int> &tiles)
164{
165 Attribute *attr;
166
167 if (map.empty()) {
168 attr = attributes.find(ATTR_STD_UV);
169 }
170 else {
171 attr = attributes.find(map);
172 }
173
174 if (attr) {
176 }
177}
178
180{
182 const size_t numpoints = points.size();
183
184 if (numpoints > 0) {
185 for (size_t i = 0; i < numpoints; i++) {
186 bnds.grow(points[i], radius[i]);
187 }
188
190 if (use_motion_blur && attr) {
191 const size_t steps_size = points.size() * (motion_steps - 1);
192 float4 *point_steps = attr->data_float4();
193
194 for (size_t i = 0; i < steps_size; i++) {
195 bnds.grow(make_float3(point_steps[i]), point_steps[i].w);
196 }
197 }
198
199 if (!bnds.valid()) {
200 bnds = BoundBox::empty;
201
202 /* skip nan or inf coordinates */
203 for (size_t i = 0; i < numpoints; i++) {
204 bnds.grow_safe(points[i], radius[i]);
205 }
206
207 if (use_motion_blur && attr) {
208 const size_t steps_size = points.size() * (motion_steps - 1);
209 float4 *point_steps = attr->data_float4();
210
211 for (size_t i = 0; i < steps_size; i++) {
212 bnds.grow_safe(make_float3(point_steps[i]), point_steps[i].w);
213 }
214 }
215 }
216 }
217
218 if (!bnds.valid()) {
219 /* empty mesh */
220 bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
221 }
222
223 bounds = bnds;
224}
225
226void PointCloud::apply_transform(const Transform &tfm, const bool apply_to_motion)
227{
228 /* compute uniform scale */
229 const float3 c0 = transform_get_column(&tfm, 0);
230 const float3 c1 = transform_get_column(&tfm, 1);
231 const float3 c2 = transform_get_column(&tfm, 2);
232 const float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
233
234 /* apply transform to curve keys */
235 for (size_t i = 0; i < points.size(); i++) {
236 const float3 co = transform_point(&tfm, points[i]);
237 const float r = radius[i] * scalar;
238
239 /* scale for curve radius is only correct for uniform scale
240 */
241 points[i] = co;
242 radius[i] = r;
243 }
244
245 if (apply_to_motion) {
247
248 if (attr) {
249 /* apply transform to motion curve keys */
250 const size_t steps_size = points.size() * (motion_steps - 1);
251 float4 *point_steps = attr->data_float4();
252
253 for (size_t i = 0; i < steps_size; i++) {
254 const float3 co = transform_point(&tfm, make_float3(point_steps[i]));
255 const float radius = point_steps[i].w * scalar;
256
257 /* scale for curve radius is only correct for uniform
258 * scale */
259 point_steps[i] = make_float4(co);
260 point_steps[i].w = radius;
261 }
262 }
263 }
264}
265
266void PointCloud::pack(Scene *scene, float4 *packed_points, uint *packed_shader)
267{
268 const size_t numpoints = points.size();
269 float3 *points_data = points.data();
270 float *radius_data = radius.data();
271 int *shader_data = shader.data();
272
273 for (size_t i = 0; i < numpoints; i++) {
274 packed_points[i] = make_float4(points_data[i], radius_data[i]);
275 }
276
277 uint shader_id = 0;
278 uint last_shader = -1;
279 for (size_t i = 0; i < numpoints; i++) {
280 if (last_shader != shader_data[i]) {
281 last_shader = shader_data[i];
282 Shader *shader = (last_shader < used_shaders.size()) ?
283 static_cast<Shader *>(used_shaders[last_shader]) :
284 scene->default_surface;
285 shader_id = scene->shader_manager->get_shader_id(shader);
286 }
287 packed_shader[i] = shader_id;
288 }
289}
290
295
unsigned int uint
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
int motion_step(const float time) const
BoundBox bounds
virtual bool has_motion_blur() const
AttributeSet attributes
Geometry(const NodeType *node_type, const Type type)
virtual void clear(bool preserve_shaders=false)
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
PrimitiveType
@ PRIMITIVE_MOTION_POINT
@ PRIMITIVE_POINT
@ ATTR_STD_UV
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_PRIM_GEOMETRY
#define SOCKET_POINT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:268
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:259
#define SOCKET_INT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:257
#define NODE_DEFINE(structname)
Definition node_type.h:152
#define fabsf
#define make_float4
#define min(a, b)
Definition sort.cc:36
void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set< int > &tiles) const
float4 * data_float4()
__forceinline bool valid() const
Definition boundbox.h:127
__forceinline void grow_safe(const float3 &pt)
Definition boundbox.h:56
__forceinline void grow(const float3 &pt)
Definition boundbox.h:35
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=nullptr)
const NodeType * type
Definition graph/node.h:178
float4 point_for_step(const float3 *points, const float *radius, const float4 *point_steps, const size_t num_points, const size_t num_steps, const size_t step, size_t p) const
void bounds_grow(const float3 *points, const float *radius, BoundBox &bounds) const
float4 motion_key(const float3 *points, const float *radius, const float4 *point_steps, const size_t num_points, const size_t num_steps, const float time, size_t p) const
void pack(Scene *scene, float4 *packed_points, uint *packed_shader)
void clear(const bool preserve_shaders=false) override
void resize(const int numpoints)
void add_point(const float3 co, const float radius, const int shader=0)
void reserve(const int numpoints)
void apply_transform(const Transform &tfm, const bool apply_to_motion) override
void get_uv_tiles(ustring map, unordered_set< int > &tiles) override
size_t num_points() const
~PointCloud() override
void copy_center_to_motion_step(const int motion_step)
void compute_bounds() override
PrimitiveType primitive_type() const override
Shader * default_surface
Definition scene.h:157
unique_ptr< ShaderManager > shader_manager
Definition scene.h:148
float w
Definition sky_math.h:225
i
Definition text_draw.cc:230
ccl_device_inline float3 transform_get_column(const Transform *t, const int column)
Definition transform.h:354
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56