Blender V4.3
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 float3 P = transform_point(&aligned_space, points[index]);
27 bounds.grow(P, radius[index]);
28}
29
30void PointCloud::Point::bounds_grow(const float4 &point, BoundBox &bounds) const
31{
32 bounds.grow(float4_to_float3(point), point.w);
33}
34
36 const float *radius,
37 const float4 *point_steps,
38 size_t num_points,
39 size_t num_steps,
40 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 size_t num_points,
61 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].x, points[p].y, points[p].z, radius[p]);
69 }
70 else {
71 /* Center step is not stored in this array. */
72 if (step > center_step) {
73 step--;
74 }
75 const size_t offset = step * num_points;
76 return point_steps[offset + p];
77 }
78}
79
80/* PointCloud */
81
83{
84 NodeType *type = NodeType::add(
85 "pointcloud", create, NodeType::NONE, Geometry::get_node_base_type());
86
87 SOCKET_POINT_ARRAY(points, "Points", array<float3>());
88 SOCKET_FLOAT_ARRAY(radius, "Radius", array<float>());
89 SOCKET_INT_ARRAY(shader, "Shader", array<int>());
90
91 return type;
92}
93
95
97
98void PointCloud::resize(int numpoints)
99{
100 points.resize(numpoints);
101 radius.resize(numpoints);
102 shader.resize(numpoints);
103 attributes.resize();
104
105 tag_points_modified();
106 tag_radius_modified();
107 tag_shader_modified();
108}
109
110void PointCloud::reserve(int numpoints)
111{
112 points.reserve(numpoints);
113 radius.reserve(numpoints);
114 shader.reserve(numpoints);
115 attributes.resize(true);
116}
117
118void PointCloud::clear(const bool preserve_shaders)
119{
120 Geometry::clear(preserve_shaders);
121
122 points.clear();
123 radius.clear();
124 shader.clear();
125 attributes.clear();
126
127 tag_points_modified();
128 tag_radius_modified();
129 tag_shader_modified();
130}
131
132void PointCloud::add_point(float3 co, float r, int shader_index)
133{
134 points.push_back_reserved(co);
135 radius.push_back_reserved(r);
136 shader.push_back_reserved(shader_index);
137
138 tag_points_modified();
139 tag_radius_modified();
140 tag_shader_modified();
141}
142
143void PointCloud::copy_center_to_motion_step(const int motion_step)
144{
145 Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
146 if (attr_mP) {
147 float3 *points_data = points.data();
148 size_t numpoints = points.size();
149 float *radius_data = radius.data();
150
151 float4 *attrib_P = attr_mP->data_float4() + motion_step * numpoints;
152 for (int i = 0; i < numpoints; i++) {
153 float3 P = points_data[i];
154 float r = radius_data[i];
155 attrib_P[i] = make_float4(P.x, P.y, P.z, r);
156 }
157 }
158}
159
160void PointCloud::get_uv_tiles(ustring map, unordered_set<int> &tiles)
161{
162 Attribute *attr;
163
164 if (map.empty()) {
165 attr = attributes.find(ATTR_STD_UV);
166 }
167 else {
168 attr = attributes.find(map);
169 }
170
171 if (attr) {
173 }
174}
175
177{
179 size_t numpoints = points.size();
180
181 if (numpoints > 0) {
182 for (size_t i = 0; i < numpoints; i++) {
183 bnds.grow(points[i], radius[i]);
184 }
185
186 Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
187 if (use_motion_blur && attr) {
188 size_t steps_size = points.size() * (motion_steps - 1);
189 float4 *point_steps = attr->data_float4();
190
191 for (size_t i = 0; i < steps_size; i++) {
192 bnds.grow(float4_to_float3(point_steps[i]), point_steps[i].w);
193 }
194 }
195
196 if (!bnds.valid()) {
197 bnds = BoundBox::empty;
198
199 /* skip nan or inf coordinates */
200 for (size_t i = 0; i < numpoints; i++) {
201 bnds.grow_safe(points[i], radius[i]);
202 }
203
204 if (use_motion_blur && attr) {
205 size_t steps_size = points.size() * (motion_steps - 1);
206 float4 *point_steps = attr->data_float4();
207
208 for (size_t i = 0; i < steps_size; i++) {
209 bnds.grow_safe(float4_to_float3(point_steps[i]), point_steps[i].w);
210 }
211 }
212 }
213 }
214
215 if (!bnds.valid()) {
216 /* empty mesh */
217 bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
218 }
219
220 bounds = bnds;
221}
222
223void PointCloud::apply_transform(const Transform &tfm, const bool apply_to_motion)
224{
225 /* compute uniform scale */
226 float3 c0 = transform_get_column(&tfm, 0);
227 float3 c1 = transform_get_column(&tfm, 1);
228 float3 c2 = transform_get_column(&tfm, 2);
229 float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
230
231 /* apply transform to curve keys */
232 for (size_t i = 0; i < points.size(); i++) {
233 float3 co = transform_point(&tfm, points[i]);
234 float r = radius[i] * scalar;
235
236 /* scale for curve radius is only correct for uniform scale
237 */
238 points[i] = co;
239 radius[i] = r;
240 }
241
242 if (apply_to_motion) {
243 Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
244
245 if (attr) {
246 /* apply transform to motion curve keys */
247 size_t steps_size = points.size() * (motion_steps - 1);
248 float4 *point_steps = attr->data_float4();
249
250 for (size_t i = 0; i < steps_size; i++) {
251 float3 co = transform_point(&tfm, float4_to_float3(point_steps[i]));
252 float radius = point_steps[i].w * scalar;
253
254 /* scale for curve radius is only correct for uniform
255 * scale */
256 point_steps[i] = float3_to_float4(co);
257 point_steps[i].w = radius;
258 }
259 }
260 }
261}
262
263void PointCloud::pack(Scene *scene, float4 *packed_points, uint *packed_shader)
264{
265 size_t numpoints = points.size();
266 float3 *points_data = points.data();
267 float *radius_data = radius.data();
268 int *shader_data = shader.data();
269
270 for (size_t i = 0; i < numpoints; i++) {
271 packed_points[i] = make_float4(
272 points_data[i].x, points_data[i].y, points_data[i].z, radius_data[i]);
273 }
274
275 uint shader_id = 0;
276 uint last_shader = -1;
277 for (size_t i = 0; i < numpoints; i++) {
278 if (last_shader != shader_data[i]) {
279 last_shader = shader_data[i];
280 Shader *shader = (last_shader < used_shaders.size()) ?
281 static_cast<Shader *>(used_shaders[last_shader]) :
282 scene->default_surface;
283 shader_id = scene->shader_manager->get_shader_id(shader);
284 }
285 packed_shader[i] = shader_id;
286 }
287}
288
293
unsigned int uint
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set< int > &tiles) const
float4 * data_float4()
BoundBox bounds
int motion_step(float time) const
bool has_motion_blur() const
virtual void clear(bool preserve_shaders=false)
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fabsf(x)
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
ccl_device_inline float cross(const float2 a, const float2 b)
#define SOCKET_POINT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:257
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:248
#define SOCKET_INT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:246
#define NODE_DEFINE(structname)
Definition node_type.h:148
#define min(a, b)
Definition sort.c:32
__forceinline bool valid() const
Definition boundbox.h:128
__forceinline float3 size() const
Definition boundbox.h:123
__forceinline void grow_safe(const float3 &pt)
Definition boundbox.h:57
__forceinline void grow(const float3 &pt)
Definition boundbox.h:36
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
const NodeType * type
Definition graph/node.h:178
float4 motion_key(const float3 *points, const float *radius, const float4 *point_steps, size_t num_points, size_t num_steps, float time, size_t p) const
void bounds_grow(const float3 *points, const float *radius, BoundBox &bounds) const
float4 point_for_step(const float3 *points, const float *radius, const float4 *point_steps, size_t num_points, size_t num_steps, size_t step, size_t p) const
void pack(Scene *scene, float4 *packed_points, uint *packed_shader)
void reserve(int numpoints)
void clear(const bool preserver_shaders=false) override
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
void resize(int numpoints)
void copy_center_to_motion_step(const int motion_step)
void compute_bounds() override
PrimitiveType primitive_type() const override
void add_point(float3 loc, float radius, int shader=0)
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
Definition transform.h:326
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
ccl_device_inline float4 float3_to_float4(const float3 a)
Definition util/math.h:540
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition util/math.h:535