Blender  V3.3
hair_volume.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_math.h"
11 #include "BLI_utildefines.h"
12 
13 #include "DNA_texture_types.h"
14 
15 #include "BKE_effect.h"
16 
17 #include "eigen_utils.h"
18 #include "implicit.h"
19 
20 /* ================ Volumetric Hair Interaction ================
21  * adapted from
22  *
23  * Volumetric Methods for Simulation and Rendering of Hair
24  * (Petrovic, Henne, Anderson, Pixar Technical Memo #06-08, Pixar Animation Studios)
25  *
26  * as well as
27  *
28  * "Detail Preserving Continuum Simulation of Straight Hair"
29  * (McAdams, Selle 2009)
30  */
31 
32 /* Note about array indexing:
33  * Generally the arrays here are one-dimensional.
34  * The relation between 3D indices and the array offset is
35  * offset = x + res_x * y + res_x * res_y * z
36  */
37 
38 static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
39 
40 BLI_INLINE int floor_int(float value)
41 {
42  return value > 0.0f ? (int)value : ((int)value) - 1;
43 }
44 
45 BLI_INLINE float floor_mod(float value)
46 {
47  return value - floorf(value);
48 }
49 
50 BLI_INLINE int hair_grid_size(const int res[3])
51 {
52  return res[0] * res[1] * res[2];
53 }
54 
55 struct HairGridVert {
56  int samples;
57  float velocity[3];
58  float density;
59 
60  float velocity_smooth[3];
61 };
62 
63 struct HairGrid {
65  int res[3];
66  float gmin[3], gmax[3];
68 };
69 
70 #define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) \
71  (min_ii(max_ii((int)((vec[axis] - gmin[axis]) * scale), 0), res[axis] - 2))
72 
73 BLI_INLINE int hair_grid_offset(const float vec[3],
74  const int res[3],
75  const float gmin[3],
76  float scale)
77 {
78  int i, j, k;
79  i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
80  j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
81  k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
82  return i + (j + k * res[1]) * res[0];
83 }
84 
86  const int res[3], const float gmin[3], float scale, const float vec[3], float uvw[3])
87 {
88  int i, j, k, offset;
89 
90  i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
91  j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
92  k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
93  offset = i + (j + k * res[1]) * res[0];
94 
95  uvw[0] = (vec[0] - gmin[0]) * scale - (float)i;
96  uvw[1] = (vec[1] - gmin[1]) * scale - (float)j;
97  uvw[2] = (vec[2] - gmin[2]) * scale - (float)k;
98 
99 #if 0
100  BLI_assert(0.0f <= uvw[0] && uvw[0] <= 1.0001f);
101  BLI_assert(0.0f <= uvw[1] && uvw[1] <= 1.0001f);
102  BLI_assert(0.0f <= uvw[2] && uvw[2] <= 1.0001f);
103 #endif
104 
105  return offset;
106 }
107 
109  const int res[3],
110  const float gmin[3],
111  float scale,
112  const float vec[3],
113  float *density,
114  float velocity[3],
115  float vel_smooth[3],
116  float density_gradient[3],
117  float velocity_gradient[3][3])
118 {
119  HairGridVert data[8];
120  float uvw[3], muvw[3];
121  int res2 = res[1] * res[0];
122  int offset;
123 
124  offset = hair_grid_interp_weights(res, gmin, scale, vec, uvw);
125  muvw[0] = 1.0f - uvw[0];
126  muvw[1] = 1.0f - uvw[1];
127  muvw[2] = 1.0f - uvw[2];
128 
129  data[0] = grid[offset];
130  data[1] = grid[offset + 1];
131  data[2] = grid[offset + res[0]];
132  data[3] = grid[offset + res[0] + 1];
133  data[4] = grid[offset + res2];
134  data[5] = grid[offset + res2 + 1];
135  data[6] = grid[offset + res2 + res[0]];
136  data[7] = grid[offset + res2 + res[0] + 1];
137 
138  if (density) {
139  *density = muvw[2] * (muvw[1] * (muvw[0] * data[0].density + uvw[0] * data[1].density) +
140  uvw[1] * (muvw[0] * data[2].density + uvw[0] * data[3].density)) +
141  uvw[2] * (muvw[1] * (muvw[0] * data[4].density + uvw[0] * data[5].density) +
142  uvw[1] * (muvw[0] * data[6].density + uvw[0] * data[7].density));
143  }
144 
145  if (velocity) {
146  int k;
147  for (k = 0; k < 3; k++) {
148  velocity[k] = muvw[2] *
149  (muvw[1] * (muvw[0] * data[0].velocity[k] + uvw[0] * data[1].velocity[k]) +
150  uvw[1] * (muvw[0] * data[2].velocity[k] + uvw[0] * data[3].velocity[k])) +
151  uvw[2] *
152  (muvw[1] * (muvw[0] * data[4].velocity[k] + uvw[0] * data[5].velocity[k]) +
153  uvw[1] * (muvw[0] * data[6].velocity[k] + uvw[0] * data[7].velocity[k]));
154  }
155  }
156 
157  if (vel_smooth) {
158  int k;
159  for (k = 0; k < 3; k++) {
160  vel_smooth[k] = muvw[2] * (muvw[1] * (muvw[0] * data[0].velocity_smooth[k] +
161  uvw[0] * data[1].velocity_smooth[k]) +
162  uvw[1] * (muvw[0] * data[2].velocity_smooth[k] +
163  uvw[0] * data[3].velocity_smooth[k])) +
164  uvw[2] * (muvw[1] * (muvw[0] * data[4].velocity_smooth[k] +
165  uvw[0] * data[5].velocity_smooth[k]) +
166  uvw[1] * (muvw[0] * data[6].velocity_smooth[k] +
167  uvw[0] * data[7].velocity_smooth[k]));
168  }
169  }
170 
171  if (density_gradient) {
172  density_gradient[0] = muvw[1] * muvw[2] * (data[0].density - data[1].density) +
173  uvw[1] * muvw[2] * (data[2].density - data[3].density) +
174  muvw[1] * uvw[2] * (data[4].density - data[5].density) +
175  uvw[1] * uvw[2] * (data[6].density - data[7].density);
176 
177  density_gradient[1] = muvw[2] * muvw[0] * (data[0].density - data[2].density) +
178  uvw[2] * muvw[0] * (data[4].density - data[6].density) +
179  muvw[2] * uvw[0] * (data[1].density - data[3].density) +
180  uvw[2] * uvw[0] * (data[5].density - data[7].density);
181 
182  density_gradient[2] = muvw[2] * muvw[0] * (data[0].density - data[4].density) +
183  uvw[2] * muvw[0] * (data[1].density - data[5].density) +
184  muvw[2] * uvw[0] * (data[2].density - data[6].density) +
185  uvw[2] * uvw[0] * (data[3].density - data[7].density);
186  }
187 
188  if (velocity_gradient) {
189  /* XXX TODO: */
190  zero_m3(velocity_gradient);
191  }
192 }
193 
195  const float x[3],
196  const float v[3],
197  float smoothfac,
198  float pressurefac,
199  float minpressure,
200  float f[3],
201  float dfdx[3][3],
202  float dfdv[3][3])
203 {
204  float gdensity, gvelocity[3], ggrad[3], gvelgrad[3][3], gradlen;
205 
207  grid->res,
208  grid->gmin,
209  grid->inv_cellsize,
210  x,
211  &gdensity,
212  gvelocity,
213  nullptr,
214  ggrad,
215  gvelgrad);
216 
217  zero_v3(f);
218  sub_v3_v3(gvelocity, v);
219  mul_v3_v3fl(f, gvelocity, smoothfac);
220 
221  gradlen = normalize_v3(ggrad) - minpressure;
222  if (gradlen > 0.0f) {
223  mul_v3_fl(ggrad, gradlen);
224  madd_v3_v3fl(f, ggrad, pressurefac);
225  }
226 
227  zero_m3(dfdx);
228 
229  sub_m3_m3m3(dfdv, gvelgrad, I);
230  mul_m3_fl(dfdv, smoothfac);
231 }
232 
234  const float x[3],
235  float *density,
236  float velocity[3],
237  float velocity_smooth[3],
238  float density_gradient[3],
239  float velocity_gradient[3][3])
240 {
242  grid->res,
243  grid->gmin,
244  grid->inv_cellsize,
245  x,
246  density,
247  velocity,
248  velocity_smooth,
249  density_gradient,
250  velocity_gradient);
251 }
252 
254  HairGrid *grid, const float x[3], const float v[3], float fluid_factor, float r_v[3])
255 {
256  float gdensity, gvelocity[3], gvel_smooth[3], ggrad[3], gvelgrad[3][3];
257  float v_pic[3], v_flip[3];
258 
260  grid->res,
261  grid->gmin,
262  grid->inv_cellsize,
263  x,
264  &gdensity,
265  gvelocity,
266  gvel_smooth,
267  ggrad,
268  gvelgrad);
269 
270  /* velocity according to PIC method (Particle-in-Cell) */
271  copy_v3_v3(v_pic, gvel_smooth);
272 
273  /* velocity according to FLIP method (Fluid-Implicit-Particle) */
274  sub_v3_v3v3(v_flip, gvel_smooth, gvelocity);
275  add_v3_v3(v_flip, v);
276 
277  interp_v3_v3v3(r_v, v_pic, v_flip, fluid_factor);
278 }
279 
281 {
282  const int size = hair_grid_size(grid->res);
283  int i;
284  for (i = 0; i < size; i++) {
285  zero_v3(grid->verts[i].velocity);
286  zero_v3(grid->verts[i].velocity_smooth);
287  grid->verts[i].density = 0.0f;
288  grid->verts[i].samples = 0;
289  }
290 }
291 
292 BLI_INLINE bool hair_grid_point_valid(const float vec[3], const float gmin[3], const float gmax[3])
293 {
294  return !(vec[0] < gmin[0] || vec[1] < gmin[1] || vec[2] < gmin[2] || vec[0] > gmax[0] ||
295  vec[1] > gmax[1] || vec[2] > gmax[2]);
296 }
297 
298 BLI_INLINE float dist_tent_v3f3(const float a[3], float x, float y, float z)
299 {
300  float w = (1.0f - fabsf(a[0] - x)) * (1.0f - fabsf(a[1] - y)) * (1.0f - fabsf(a[2] - z));
301  return w;
302 }
303 
304 BLI_INLINE float weights_sum(const float weights[8])
305 {
306  float totweight = 0.0f;
307  int i;
308  for (i = 0; i < 8; i++) {
309  totweight += weights[i];
310  }
311  return totweight;
312 }
313 
314 /* returns the grid array offset as well to avoid redundant calculation */
316  const int res[3], const float gmin[3], float scale, const float vec[3], float weights[8])
317 {
318  int i, j, k, offset;
319  float uvw[3];
320 
321  i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
322  j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
323  k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
324  offset = i + (j + k * res[1]) * res[0];
325 
326  uvw[0] = (vec[0] - gmin[0]) * scale;
327  uvw[1] = (vec[1] - gmin[1]) * scale;
328  uvw[2] = (vec[2] - gmin[2]) * scale;
329 
330  weights[0] = dist_tent_v3f3(uvw, (float)i, (float)j, (float)k);
331  weights[1] = dist_tent_v3f3(uvw, (float)(i + 1), (float)j, (float)k);
332  weights[2] = dist_tent_v3f3(uvw, (float)i, (float)(j + 1), (float)k);
333  weights[3] = dist_tent_v3f3(uvw, (float)(i + 1), (float)(j + 1), (float)k);
334  weights[4] = dist_tent_v3f3(uvw, (float)i, (float)j, (float)(k + 1));
335  weights[5] = dist_tent_v3f3(uvw, (float)(i + 1), (float)j, (float)(k + 1));
336  weights[6] = dist_tent_v3f3(uvw, (float)i, (float)(j + 1), (float)(k + 1));
337  weights[7] = dist_tent_v3f3(uvw, (float)(i + 1), (float)(j + 1), (float)(k + 1));
338 
339  // BLI_assert(fabsf(weights_sum(weights) - 1.0f) < 0.0001f);
340 
341  return offset;
342 }
343 
344 BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3])
345 {
346  copy_v3_v3(vecw, vec);
347  mul_v3_fl(vecw, grid->cellsize);
348  add_v3_v3(vecw, grid->gmin);
349 }
350 
351 void SIM_hair_volume_add_vertex(HairGrid *grid, const float x[3], const float v[3])
352 {
353  const int res[3] = {grid->res[0], grid->res[1], grid->res[2]};
354  float weights[8];
355  int di, dj, dk;
356  int offset;
357 
358  if (!hair_grid_point_valid(x, grid->gmin, grid->gmax)) {
359  return;
360  }
361 
362  offset = hair_grid_weights(res, grid->gmin, grid->inv_cellsize, x, weights);
363 
364  for (di = 0; di < 2; di++) {
365  for (dj = 0; dj < 2; dj++) {
366  for (dk = 0; dk < 2; dk++) {
367  int voffset = offset + di + (dj + dk * res[1]) * res[0];
368  int iw = di + dj * 2 + dk * 4;
369 
370  grid->verts[voffset].density += weights[iw];
371  madd_v3_v3fl(grid->verts[voffset].velocity, v, weights[iw]);
372  }
373  }
374  }
375 }
376 
377 #if 0
378 BLI_INLINE void hair_volume_eval_grid_vertex(HairGridVert *vert,
379  const float loc[3],
380  float radius,
381  float dist_scale,
382  const float x2[3],
383  const float v2[3],
384  const float x3[3],
385  const float v3[3])
386 {
387  float closest[3], lambda, dist, weight;
388 
389  lambda = closest_to_line_v3(closest, loc, x2, x3);
390  dist = len_v3v3(closest, loc);
391 
392  weight = (radius - dist) * dist_scale;
393 
394  if (weight > 0.0f) {
395  float vel[3];
396 
397  interp_v3_v3v3(vel, v2, v3, lambda);
398  madd_v3_v3fl(vert->velocity, vel, weight);
399  vert->density += weight;
400  vert->samples += 1;
401  }
402 }
403 
404 BLI_INLINE int major_axis_v3(const float v[3])
405 {
406  const float a = fabsf(v[0]);
407  const float b = fabsf(v[1]);
408  const float c = fabsf(v[2]);
409  return a > b ? (a > c ? 0 : 2) : (b > c ? 1 : 2);
410 }
411 
412 BLI_INLINE void hair_volume_add_segment_2D(HairGrid *grid,
413  const float UNUSED(x1[3]),
414  const float UNUSED(v1[3]),
415  const float x2[3],
416  const float v2[3],
417  const float x3[3],
418  const float v3[3],
419  const float UNUSED(x4[3]),
420  const float UNUSED(v4[3]),
421  const float UNUSED(dir1[3]),
422  const float dir2[3],
423  const float UNUSED(dir3[3]),
424  int resj,
425  int resk,
426  int jmin,
427  int jmax,
428  int kmin,
429  int kmax,
430  HairGridVert *vert,
431  int stride_j,
432  int stride_k,
433  const float loc[3],
434  int axis_j,
435  int axis_k,
436  int debug_i)
437 {
438  const float radius = 1.5f;
439  const float dist_scale = grid->inv_cellsize;
440 
441  int j, k;
442 
443  /* boundary checks to be safe */
444  CLAMP_MIN(jmin, 0);
445  CLAMP_MAX(jmax, resj - 1);
446  CLAMP_MIN(kmin, 0);
447  CLAMP_MAX(kmax, resk - 1);
448 
449  HairGridVert *vert_j = vert + jmin * stride_j;
450  float loc_j[3] = {loc[0], loc[1], loc[2]};
451  loc_j[axis_j] += (float)jmin;
452  for (j = jmin; j <= jmax; j++, vert_j += stride_j, loc_j[axis_j] += 1.0f) {
453 
454  HairGridVert *vert_k = vert_j + kmin * stride_k;
455  float loc_k[3] = {loc_j[0], loc_j[1], loc_j[2]};
456  loc_k[axis_k] += (float)kmin;
457  for (k = kmin; k <= kmax; k++, vert_k += stride_k, loc_k[axis_k] += 1.0f) {
458 
459  hair_volume_eval_grid_vertex(vert_k, loc_k, radius, dist_scale, x2, v2, x3, v3);
460 
461 # if 0
462  {
463  float wloc[3], x2w[3], x3w[3];
464  grid_to_world(grid, wloc, loc_k);
465  grid_to_world(grid, x2w, x2);
466  grid_to_world(grid, x3w, x3);
467 
468  if (vert_k->samples > 0) {
469  BKE_sim_debug_data_add_circle(wloc, 0.01f, 1.0, 1.0, 0.3, "grid", 2525, debug_i, j, k);
470  }
471 
472  if (grid->debug_value) {
473  BKE_sim_debug_data_add_dot(wloc, 1, 0, 0, "grid", 93, debug_i, j, k);
474  BKE_sim_debug_data_add_dot(x2w, 0.1, 0.1, 0.7, "grid", 649, debug_i, j, k);
475  BKE_sim_debug_data_add_line(wloc, x2w, 0.3, 0.8, 0.3, "grid", 253, debug_i, j, k);
476  BKE_sim_debug_data_add_line(wloc, x3w, 0.8, 0.3, 0.3, "grid", 254, debug_i, j, k);
477 # if 0
479  x2w, len_v3v3(wloc, x2w), 0.2, 0.7, 0.2, "grid", 255, i, j, k);
480 # endif
481  }
482  }
483 # endif
484  }
485  }
486 }
487 
488 /* Uses a variation of Bresenham's algorithm for rasterizing a 3D grid with a line segment.
489  *
490  * The radius of influence around a segment is assumed to be at most 2*cellsize,
491  * i.e. only cells containing the segment and their direct neighbors are examined.
492  */
494  const float x1[3],
495  const float v1[3],
496  const float x2[3],
497  const float v2[3],
498  const float x3[3],
499  const float v3[3],
500  const float x4[3],
501  const float v4[3],
502  const float dir1[3],
503  const float dir2[3],
504  const float dir3[3])
505 {
506  const int res[3] = {grid->res[0], grid->res[1], grid->res[2]};
507 
508  /* find the primary direction from the major axis of the direction vector */
509  const int axis0 = major_axis_v3(dir2);
510  const int axis1 = (axis0 + 1) % 3;
511  const int axis2 = (axis0 + 2) % 3;
512 
513  /* vertex buffer offset factors along cardinal axes */
514  const int strides[3] = {1, res[0], res[0] * res[1]};
515  const int stride0 = strides[axis0];
516  const int stride1 = strides[axis1];
517  const int stride2 = strides[axis2];
518 
519  /* increment of secondary directions per step in the primary direction
520  * NOTE: we always go in the positive direction along axis0, so the sign can be inverted
521  */
522  const float inc1 = dir2[axis1] / dir2[axis0];
523  const float inc2 = dir2[axis2] / dir2[axis0];
524 
525  /* start/end points, so increment along axis0 is always positive */
526  const float *start = x2[axis0] < x3[axis0] ? x2 : x3;
527  const float *end = x2[axis0] < x3[axis0] ? x3 : x2;
528  const float start0 = start[axis0], start1 = start[axis1], start2 = start[axis2];
529  const float end0 = end[axis0];
530 
531  /* range along primary direction */
532  const int imin = max_ii(floor_int(start[axis0]) - 1, 0);
533  const int imax = min_ii(floor_int(end[axis0]) + 2, res[axis0] - 1);
534 
535  float h = 0.0f;
536  HairGridVert *vert0;
537  float loc0[3];
538  int j0, k0, j0_prev, k0_prev;
539  int i;
540 
541  for (i = imin; i <= imax; i++) {
542  float shift1, shift2; /* fraction of a full cell shift [0.0, 1.0) */
543  int jmin, jmax, kmin, kmax;
544 
545  h = CLAMPIS((float)i, start0, end0);
546 
547  shift1 = start1 + (h - start0) * inc1;
548  shift2 = start2 + (h - start0) * inc2;
549 
550  j0_prev = j0;
551  j0 = floor_int(shift1);
552 
553  k0_prev = k0;
554  k0 = floor_int(shift2);
555 
556  if (i > imin) {
557  jmin = min_ii(j0, j0_prev);
558  jmax = max_ii(j0, j0_prev);
559  kmin = min_ii(k0, k0_prev);
560  kmax = max_ii(k0, k0_prev);
561  }
562  else {
563  jmin = jmax = j0;
564  kmin = kmax = k0;
565  }
566 
567  vert0 = grid->verts + i * stride0;
568  loc0[axis0] = (float)i;
569  loc0[axis1] = 0.0f;
570  loc0[axis2] = 0.0f;
571 
572  hair_volume_add_segment_2D(grid,
573  x1,
574  v1,
575  x2,
576  v2,
577  x3,
578  v3,
579  x4,
580  v4,
581  dir1,
582  dir2,
583  dir3,
584  res[axis1],
585  res[axis2],
586  jmin - 1,
587  jmax + 2,
588  kmin - 1,
589  kmax + 2,
590  vert0,
591  stride1,
592  stride2,
593  loc0,
594  axis1,
595  axis2,
596  i);
597  }
598 }
599 #else
601  const float loc[3],
602  float radius,
603  float dist_scale,
604  const float x[3],
605  const float v[3])
606 {
607  float dist, weight;
608 
609  dist = len_v3v3(x, loc);
610 
611  weight = (radius - dist) * dist_scale;
612 
613  if (weight > 0.0f) {
614  madd_v3_v3fl(vert->velocity, v, weight);
615  vert->density += weight;
616  vert->samples += 1;
617  }
618 }
619 
621  const float UNUSED(x1[3]),
622  const float UNUSED(v1[3]),
623  const float x2[3],
624  const float v2[3],
625  const float x3[3],
626  const float v3[3],
627  const float UNUSED(x4[3]),
628  const float UNUSED(v4[3]),
629  const float UNUSED(dir1[3]),
630  const float UNUSED(dir2[3]),
631  const float UNUSED(dir3[3]))
632 {
633  /* XXX simplified test implementation using a series of discrete sample along the segment,
634  * instead of finding the closest point for all affected grid vertices. */
635 
636  const float radius = 1.5f;
637  const float dist_scale = grid->inv_cellsize;
638 
639  const int res[3] = {grid->res[0], grid->res[1], grid->res[2]};
640  const int stride[3] = {1, res[0], res[0] * res[1]};
641  const int num_samples = 10;
642 
643  int s;
644 
645  for (s = 0; s < num_samples; s++) {
646  float x[3], v[3];
647  int i, j, k;
648 
649  float f = (float)s / (float)(num_samples - 1);
650  interp_v3_v3v3(x, x2, x3, f);
651  interp_v3_v3v3(v, v2, v3, f);
652 
653  int imin = max_ii(floor_int(x[0]) - 2, 0);
654  int imax = min_ii(floor_int(x[0]) + 2, res[0] - 1);
655  int jmin = max_ii(floor_int(x[1]) - 2, 0);
656  int jmax = min_ii(floor_int(x[1]) + 2, res[1] - 1);
657  int kmin = max_ii(floor_int(x[2]) - 2, 0);
658  int kmax = min_ii(floor_int(x[2]) + 2, res[2] - 1);
659 
660  for (k = kmin; k <= kmax; k++) {
661  for (j = jmin; j <= jmax; j++) {
662  for (i = imin; i <= imax; i++) {
663  float loc[3] = {(float)i, (float)j, (float)k};
664  HairGridVert *vert = grid->verts + i * stride[0] + j * stride[1] + k * stride[2];
665 
666  hair_volume_eval_grid_vertex_sample(vert, loc, radius, dist_scale, x, v);
667  }
668  }
669  }
670  }
671 }
672 #endif
673 
675 {
676  int i, size = hair_grid_size(grid->res);
677  /* divide velocity with density */
678  for (i = 0; i < size; i++) {
679  float density = grid->verts[i].density;
680  if (density > 0.0f) {
681  mul_v3_fl(grid->verts[i].velocity, 1.0f / density);
682  }
683  }
684 }
685 
686 /* Cells with density below this are considered empty. */
687 static const float density_threshold = 0.001f;
688 
689 /* Contribution of target density pressure to the laplacian in the pressure poisson equation.
690  * This is based on the model found in
691  * "Two-way Coupled SPH and Particle Level Set Fluid Simulation" (Losasso et al., 2008)
692  */
694  float target_density,
695  float strength)
696 {
697  if (density > density_threshold && density > target_density) {
698  return strength * logf(target_density / density);
699  }
700 
701  return 0.0f;
702 }
703 
705  float /*dt*/,
706  float target_density,
707  float target_strength)
708 {
709  const float flowfac = grid->cellsize;
710  const float inv_flowfac = 1.0f / grid->cellsize;
711 
712  // const int num_cells = hair_grid_size(grid->res);
713  const int res[3] = {grid->res[0], grid->res[1], grid->res[2]};
714  const int resA[3] = {grid->res[0] + 2, grid->res[1] + 2, grid->res[2] + 2};
715 
716  const int stride0 = 1;
717  const int stride1 = grid->res[0];
718  const int stride2 = grid->res[1] * grid->res[0];
719  const int strideA0 = 1;
720  const int strideA1 = grid->res[0] + 2;
721  const int strideA2 = (grid->res[1] + 2) * (grid->res[0] + 2);
722 
723  const int num_cells = res[0] * res[1] * res[2];
724  const int num_cellsA = (res[0] + 2) * (res[1] + 2) * (res[2] + 2);
725 
726  HairGridVert *vert_start = grid->verts - (stride0 + stride1 + stride2);
727  HairGridVert *vert;
728  int i, j, k;
729 
730 #define MARGIN_i0 (i < 1)
731 #define MARGIN_j0 (j < 1)
732 #define MARGIN_k0 (k < 1)
733 #define MARGIN_i1 (i >= resA[0] - 1)
734 #define MARGIN_j1 (j >= resA[1] - 1)
735 #define MARGIN_k1 (k >= resA[2] - 1)
736 
737 #define NEIGHBOR_MARGIN_i0 (i < 2)
738 #define NEIGHBOR_MARGIN_j0 (j < 2)
739 #define NEIGHBOR_MARGIN_k0 (k < 2)
740 #define NEIGHBOR_MARGIN_i1 (i >= resA[0] - 2)
741 #define NEIGHBOR_MARGIN_j1 (j >= resA[1] - 2)
742 #define NEIGHBOR_MARGIN_k1 (k >= resA[2] - 2)
743 
744  BLI_assert(num_cells >= 1);
745 
746  /* Calculate divergence */
747  lVector B(num_cellsA);
748  for (k = 0; k < resA[2]; k++) {
749  for (j = 0; j < resA[1]; j++) {
750  for (i = 0; i < resA[0]; i++) {
751  int u = i * strideA0 + j * strideA1 + k * strideA2;
752  bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 ||
753  MARGIN_k1;
754 
755  if (is_margin) {
756  B[u] = 0.0f;
757  continue;
758  }
759 
760  vert = vert_start + i * stride0 + j * stride1 + k * stride2;
761 
762  const float *v0 = vert->velocity;
763  float dx = 0.0f, dy = 0.0f, dz = 0.0f;
764  if (!NEIGHBOR_MARGIN_i0) {
765  dx += v0[0] - (vert - stride0)->velocity[0];
766  }
767  if (!NEIGHBOR_MARGIN_i1) {
768  dx += (vert + stride0)->velocity[0] - v0[0];
769  }
770  if (!NEIGHBOR_MARGIN_j0) {
771  dy += v0[1] - (vert - stride1)->velocity[1];
772  }
773  if (!NEIGHBOR_MARGIN_j1) {
774  dy += (vert + stride1)->velocity[1] - v0[1];
775  }
776  if (!NEIGHBOR_MARGIN_k0) {
777  dz += v0[2] - (vert - stride2)->velocity[2];
778  }
779  if (!NEIGHBOR_MARGIN_k1) {
780  dz += (vert + stride2)->velocity[2] - v0[2];
781  }
782 
783  float divergence = -0.5f * flowfac * (dx + dy + dz);
784 
785  /* adjustment term for target density */
786  float target = hair_volume_density_divergence(
787  vert->density, target_density, target_strength);
788 
789  /* B vector contains the finite difference approximation of the velocity divergence.
790  * NOTE: according to the discretized Navier-Stokes equation the rhs vector
791  * and resulting pressure gradient should be multiplied by the (inverse) density;
792  * however, this is already included in the weighting of hair velocities on the grid!
793  */
794  B[u] = divergence - target;
795 
796 #if 0
797  {
798  float wloc[3], loc[3];
799  float col0[3] = {0.0, 0.0, 0.0};
800  float colp[3] = {0.0, 1.0, 1.0};
801  float coln[3] = {1.0, 0.0, 1.0};
802  float col[3];
803  float fac;
804 
805  loc[0] = (float)(i - 1);
806  loc[1] = (float)(j - 1);
807  loc[2] = (float)(k - 1);
808  grid_to_world(grid, wloc, loc);
809 
810  if (divergence > 0.0f) {
811  fac = CLAMPIS(divergence * target_strength, 0.0, 1.0);
812  interp_v3_v3v3(col, col0, colp, fac);
813  }
814  else {
815  fac = CLAMPIS(-divergence * target_strength, 0.0, 1.0);
816  interp_v3_v3v3(col, col0, coln, fac);
817  }
818  if (fac > 0.05f) {
820  grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5522, i, j, k);
821  }
822  }
823 #endif
824  }
825  }
826  }
827 
828  /* Main Poisson equation system:
829  * This is derived from the discretization of the Poisson equation:
830  * `div(grad(p)) = div(v)`
831  *
832  * The finite difference approximation yields the linear equation system described here:
833  * https://en.wikipedia.org/wiki/Discrete_Poisson_equation
834  */
835  lMatrix A(num_cellsA, num_cellsA);
836  /* Reserve space for the base equation system (without boundary conditions).
837  * Each column contains a factor 6 on the diagonal
838  * and up to 6 factors -1 on other places.
839  */
840  A.reserve(Eigen::VectorXi::Constant(num_cellsA, 7));
841 
842  for (k = 0; k < resA[2]; k++) {
843  for (j = 0; j < resA[1]; j++) {
844  for (i = 0; i < resA[0]; i++) {
845  int u = i * strideA0 + j * strideA1 + k * strideA2;
846  bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 ||
847  MARGIN_k1;
848 
849  vert = vert_start + i * stride0 + j * stride1 + k * stride2;
850  if (!is_margin && vert->density > density_threshold) {
851  int neighbors_lo = 0;
852  int neighbors_hi = 0;
853  int non_solid_neighbors = 0;
854  int neighbor_lo_index[3];
855  int neighbor_hi_index[3];
856  int n;
857 
858  /* check for upper bounds in advance
859  * to get the correct number of neighbors,
860  * needed for the diagonal element
861  */
862  if (!NEIGHBOR_MARGIN_k0 && (vert - stride2)->density > density_threshold) {
863  neighbor_lo_index[neighbors_lo++] = u - strideA2;
864  }
865  if (!NEIGHBOR_MARGIN_j0 && (vert - stride1)->density > density_threshold) {
866  neighbor_lo_index[neighbors_lo++] = u - strideA1;
867  }
868  if (!NEIGHBOR_MARGIN_i0 && (vert - stride0)->density > density_threshold) {
869  neighbor_lo_index[neighbors_lo++] = u - strideA0;
870  }
871  if (!NEIGHBOR_MARGIN_i1 && (vert + stride0)->density > density_threshold) {
872  neighbor_hi_index[neighbors_hi++] = u + strideA0;
873  }
874  if (!NEIGHBOR_MARGIN_j1 && (vert + stride1)->density > density_threshold) {
875  neighbor_hi_index[neighbors_hi++] = u + strideA1;
876  }
877  if (!NEIGHBOR_MARGIN_k1 && (vert + stride2)->density > density_threshold) {
878  neighbor_hi_index[neighbors_hi++] = u + strideA2;
879  }
880 
881  // int liquid_neighbors = neighbors_lo + neighbors_hi;
882  non_solid_neighbors = 6;
883 
884  for (n = 0; n < neighbors_lo; n++) {
885  A.insert(neighbor_lo_index[n], u) = -1.0f;
886  }
887  A.insert(u, u) = (float)non_solid_neighbors;
888  for (n = 0; n < neighbors_hi; n++) {
889  A.insert(neighbor_hi_index[n], u) = -1.0f;
890  }
891  }
892  else {
893  A.insert(u, u) = 1.0f;
894  }
895  }
896  }
897  }
898 
900  cg.setMaxIterations(100);
901  cg.setTolerance(0.01f);
902 
903  cg.compute(A);
904 
905  lVector p = cg.solve(B);
906 
907  if (cg.info() == Eigen::Success) {
908  /* Calculate velocity = grad(p) */
909  for (k = 0; k < resA[2]; k++) {
910  for (j = 0; j < resA[1]; j++) {
911  for (i = 0; i < resA[0]; i++) {
912  int u = i * strideA0 + j * strideA1 + k * strideA2;
913  bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 ||
914  MARGIN_k1;
915  if (is_margin) {
916  continue;
917  }
918 
919  vert = vert_start + i * stride0 + j * stride1 + k * stride2;
920  if (vert->density > density_threshold) {
921  float p_left = p[u - strideA0];
922  float p_right = p[u + strideA0];
923  float p_down = p[u - strideA1];
924  float p_up = p[u + strideA1];
925  float p_bottom = p[u - strideA2];
926  float p_top = p[u + strideA2];
927 
928  /* finite difference estimate of pressure gradient */
929  float dvel[3];
930  dvel[0] = p_right - p_left;
931  dvel[1] = p_up - p_down;
932  dvel[2] = p_top - p_bottom;
933  mul_v3_fl(dvel, -0.5f * inv_flowfac);
934 
935  /* pressure gradient describes velocity delta */
936  add_v3_v3v3(vert->velocity_smooth, vert->velocity, dvel);
937  }
938  else {
939  zero_v3(vert->velocity_smooth);
940  }
941  }
942  }
943  }
944 
945 #if 0
946  {
947  int axis = 0;
948  float offset = 0.0f;
949 
950  int slice = (offset - grid->gmin[axis]) / grid->cellsize;
951 
952  for (k = 0; k < resA[2]; k++) {
953  for (j = 0; j < resA[1]; j++) {
954  for (i = 0; i < resA[0]; i++) {
955  int u = i * strideA0 + j * strideA1 + k * strideA2;
956  bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 ||
957  MARGIN_k1;
958  if (i != slice) {
959  continue;
960  }
961 
962  vert = vert_start + i * stride0 + j * stride1 + k * stride2;
963 
964  float wloc[3], loc[3];
965  float col0[3] = {0.0, 0.0, 0.0};
966  float colp[3] = {0.0, 1.0, 1.0};
967  float coln[3] = {1.0, 0.0, 1.0};
968  float col[3];
969  float fac;
970 
971  loc[0] = (float)(i - 1);
972  loc[1] = (float)(j - 1);
973  loc[2] = (float)(k - 1);
974  grid_to_world(grid, wloc, loc);
975 
976  float pressure = p[u];
977  if (pressure > 0.0f) {
978  fac = CLAMPIS(pressure * grid->debug1, 0.0, 1.0);
979  interp_v3_v3v3(col, col0, colp, fac);
980  }
981  else {
982  fac = CLAMPIS(-pressure * grid->debug1, 0.0, 1.0);
983  interp_v3_v3v3(col, col0, coln, fac);
984  }
985  if (fac > 0.05f) {
987  grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5533, i, j, k);
988  }
989 
990  if (!is_margin) {
991  float dvel[3];
992  sub_v3_v3v3(dvel, vert->velocity_smooth, vert->velocity);
993 # if 0
995  grid->debug_data, wloc, dvel, 1, 1, 1, "grid", 5566, i, j, k);
996 # endif
997  }
998 
999  if (!is_margin) {
1000  float d = CLAMPIS(vert->density * grid->debug2, 0.0f, 1.0f);
1001  float col0[3] = {0.3, 0.3, 0.3};
1002  float colp[3] = {0.0, 0.0, 1.0};
1003  float col[3];
1004 
1005  interp_v3_v3v3(col, col0, colp, d);
1006 # if 0
1007  if (d > 0.05f) {
1009  grid->debug_data, wloc, col[0], col[1], col[2], "grid", 5544, i, j, k);
1010  }
1011 # endif
1012  }
1013  }
1014  }
1015  }
1016  }
1017 #endif
1018 
1019  return true;
1020  }
1021 
1022  /* Clear result in case of error */
1023  for (i = 0, vert = grid->verts; i < num_cells; i++, vert++) {
1024  zero_v3(vert->velocity_smooth);
1025  }
1026 
1027  return false;
1028 }
1029 
1030 #if 0 /* XXX weighting is incorrect, disabled for now */
1031 /* Velocity filter kernel
1032  * See https://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29
1033  */
1034 
1035 BLI_INLINE void hair_volume_filter_box_convolute(
1036  HairVertexGrid *grid, float invD, const int kernel_size[3], int i, int j, int k)
1037 {
1038  int res = grid->res;
1039  int p, q, r;
1040  int minp = max_ii(i - kernel_size[0], 0), maxp = min_ii(i + kernel_size[0], res - 1);
1041  int minq = max_ii(j - kernel_size[1], 0), maxq = min_ii(j + kernel_size[1], res - 1);
1042  int minr = max_ii(k - kernel_size[2], 0), maxr = min_ii(k + kernel_size[2], res - 1);
1043  int offset, kernel_offset, kernel_dq, kernel_dr;
1045  float *vel_smooth;
1046 
1047  offset = i + (j + k * res) * res;
1048  verts = grid->verts;
1049  vel_smooth = verts[offset].velocity_smooth;
1050 
1051  kernel_offset = minp + (minq + minr * res) * res;
1052  kernel_dq = res;
1053  kernel_dr = res * res;
1054  for (r = minr; r <= maxr; r++) {
1055  for (q = minq; q <= maxq; q++) {
1056  for (p = minp; p <= maxp; p++) {
1057 
1058  madd_v3_v3fl(vel_smooth, verts[kernel_offset].velocity, invD);
1059 
1060  kernel_offset += 1;
1061  }
1062  kernel_offset += kernel_dq;
1063  }
1064  kernel_offset += kernel_dr;
1065  }
1066 }
1067 
1068 void SIM_hair_volume_vertex_grid_filter_box(HairVertexGrid *grid, int kernel_size)
1069 {
1070  int size = hair_grid_size(grid->res);
1071  int kernel_sizev[3] = {kernel_size, kernel_size, kernel_size};
1072  int tot;
1073  float invD;
1074  int i, j, k;
1075 
1076  if (kernel_size <= 0) {
1077  return;
1078  }
1079 
1080  tot = kernel_size * 2 + 1;
1081  invD = 1.0f / (float)(tot * tot * tot);
1082 
1083  /* clear values for convolution */
1084  for (i = 0; i < size; i++) {
1085  zero_v3(grid->verts[i].velocity_smooth);
1086  }
1087 
1088  for (i = 0; i < grid->res; i++) {
1089  for (j = 0; j < grid->res; j++) {
1090  for (k = 0; k < grid->res; k++) {
1091  hair_volume_filter_box_convolute(grid, invD, kernel_sizev, i, j, k);
1092  }
1093  }
1094  }
1095 
1096  /* apply as new velocity */
1097  for (i = 0; i < size; i++) {
1098  copy_v3_v3(grid->verts[i].velocity, grid->verts[i].velocity_smooth);
1099  }
1100 }
1101 #endif
1102 
1104  const float gmin[3],
1105  const float gmax[3])
1106 {
1107  float scale;
1108  float extent[3];
1109  int resmin[3], resmax[3], res[3];
1110  float gmin_margin[3], gmax_margin[3];
1111  int size;
1112  HairGrid *grid;
1113  int i;
1114 
1115  /* sanity check */
1116  if (cellsize <= 0.0f) {
1117  cellsize = 1.0f;
1118  }
1119  scale = 1.0f / cellsize;
1120 
1121  sub_v3_v3v3(extent, gmax, gmin);
1122  for (i = 0; i < 3; i++) {
1123  resmin[i] = floor_int(gmin[i] * scale);
1124  resmax[i] = floor_int(gmax[i] * scale) + 1;
1125 
1126  /* add margin of 1 cell */
1127  resmin[i] -= 1;
1128  resmax[i] += 1;
1129 
1130  res[i] = resmax[i] - resmin[i] + 1;
1131  /* sanity check: avoid null-sized grid */
1132  if (res[i] < 4) {
1133  res[i] = 4;
1134  resmax[i] = resmin[i] + 4;
1135  }
1136  /* sanity check: avoid too large grid size */
1137  if (res[i] > MAX_HAIR_GRID_RES) {
1138  res[i] = MAX_HAIR_GRID_RES;
1139  resmax[i] = resmin[i] + MAX_HAIR_GRID_RES;
1140  }
1141 
1142  gmin_margin[i] = (float)resmin[i] * cellsize;
1143  gmax_margin[i] = (float)resmax[i] * cellsize;
1144  }
1145  size = hair_grid_size(res);
1146 
1147  grid = MEM_cnew<HairGrid>("hair grid");
1148  grid->res[0] = res[0];
1149  grid->res[1] = res[1];
1150  grid->res[2] = res[2];
1151  copy_v3_v3(grid->gmin, gmin_margin);
1152  copy_v3_v3(grid->gmax, gmax_margin);
1153  grid->cellsize = cellsize;
1154  grid->inv_cellsize = scale;
1155  grid->verts = (HairGridVert *)MEM_callocN(sizeof(HairGridVert) * size, "hair voxel data");
1156 
1157  return grid;
1158 }
1159 
1161 {
1162  if (grid) {
1163  if (grid->verts) {
1164  MEM_freeN(grid->verts);
1165  }
1166  MEM_freeN(grid);
1167  }
1168 }
1169 
1171  HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3])
1172 {
1173  if (cellsize) {
1174  *cellsize = grid->cellsize;
1175  }
1176  if (res) {
1177  copy_v3_v3_int(res, grid->res);
1178  }
1179  if (gmin) {
1180  copy_v3_v3(gmin, grid->gmin);
1181  }
1182  if (gmax) {
1183  copy_v3_v3(gmax, grid->gmax);
1184  }
1185 }
1186 
1187 #if 0
1188 static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd,
1189  lfVector *lX,
1190  unsigned int numverts)
1191 {
1192  int res = hair_grid_res;
1193  int size = hair_grid_size(res);
1194  HairGridVert *collgrid;
1195  ListBase *colliders;
1196  ColliderCache *col = NULL;
1197  float gmin[3], gmax[3], scale[3];
1198  /* 2.0f is an experimental value that seems to give good results */
1199  float collfac = 2.0f * clmd->sim_parms->collider_friction;
1200  unsigned int v = 0;
1201  int i = 0;
1202 
1203  hair_volume_get_boundbox(lX, numverts, gmin, gmax);
1204  hair_grid_get_scale(res, gmin, gmax, scale);
1205 
1206  collgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair collider voxel data");
1207 
1208  /* initialize grid */
1209  for (i = 0; i < size; i++) {
1210  zero_v3(collgrid[i].velocity);
1211  collgrid[i].density = 0.0f;
1212  }
1213 
1214  /* gather colliders */
1216  if (colliders && collfac > 0.0f) {
1217  for (col = colliders->first; col; col = col->next) {
1218  MVert *loc0 = col->collmd->x;
1219  MVert *loc1 = col->collmd->xnew;
1220  float vel[3];
1221  float weights[8];
1222  int di, dj, dk;
1223 
1224  for (v = 0; v < col->collmd->numverts; v++, loc0++, loc1++) {
1225  int offset;
1226 
1227  if (!hair_grid_point_valid(loc1->co, gmin, gmax)) {
1228  continue;
1229  }
1230 
1231  offset = hair_grid_weights(res, gmin, scale, lX[v], weights);
1232 
1233  sub_v3_v3v3(vel, loc1->co, loc0->co);
1234 
1235  for (di = 0; di < 2; di++) {
1236  for (dj = 0; dj < 2; dj++) {
1237  for (dk = 0; dk < 2; dk++) {
1238  int voffset = offset + di + (dj + dk * res) * res;
1239  int iw = di + dj * 2 + dk * 4;
1240 
1241  collgrid[voffset].density += weights[iw];
1242  madd_v3_v3fl(collgrid[voffset].velocity, vel, weights[iw]);
1243  }
1244  }
1245  }
1246  }
1247  }
1248  }
1249  BKE_collider_cache_free(&colliders);
1250 
1251  /* divide velocity with density */
1252  for (i = 0; i < size; i++) {
1253  float density = collgrid[i].density;
1254  if (density > 0.0f) {
1255  mul_v3_fl(collgrid[i].velocity, 1.0f / density);
1256  }
1257  }
1258 
1259  return collgrid;
1260 }
1261 #endif
typedef float(TangentPoint)[2]
void BKE_collider_cache_free(struct ListBase **colliders)
Definition: collision.c:1359
struct ListBase * BKE_collider_cache_create(struct Depsgraph *depsgraph, struct Object *self, struct Collection *collection)
Definition: collision.c:1322
#define BKE_sim_debug_data_add_dot(p, r, g, b, category,...)
Definition: BKE_effect.h:238
#define BKE_sim_debug_data_add_vector(p, d, r, g, b, category,...)
Definition: BKE_effect.h:258
#define BKE_sim_debug_data_add_line(p1, p2, r, g, b, category,...)
Definition: BKE_effect.h:252
#define BKE_sim_debug_data_add_circle(p, radius, r, g, b, category,...)
Definition: BKE_effect.h:245
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3176
void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:1076
void mul_m3_fl(float R[3][3], float f)
Definition: math_matrix.c:956
void zero_m3(float m[3][3])
Definition: math_matrix.c:23
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
#define CLAMP_MAX(a, c)
#define CLAMPIS(a, b, c)
#define UNUSED(x)
#define CLAMP_MIN(a, b)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
bool closest(btVector3 &v)
#define logf(x)
Definition: cuda/compat.h:105
const Depsgraph * depsgraph
Eigen::ConjugateGradient< lMatrix, Eigen::Lower, Eigen::DiagonalPreconditioner< Scalar > > ConjugateGradient
Definition: eigen_utils.h:186
Eigen::VectorXf lVector
Definition: eigen_utils.h:96
Eigen::SparseMatrix< Scalar > lMatrix
Definition: eigen_utils.h:129
static float verts[][3]
uint col
BLI_INLINE int hair_grid_interp_weights(const int res[3], const float gmin[3], float scale, const float vec[3], float uvw[3])
Definition: hair_volume.cpp:85
#define MARGIN_k0
#define NEIGHBOR_MARGIN_j0
#define MARGIN_i1
#define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis)
Definition: hair_volume.cpp:70
#define NEIGHBOR_MARGIN_k0
#define MARGIN_j0
void SIM_hair_volume_grid_velocity(HairGrid *grid, const float x[3], const float v[3], float fluid_factor, float r_v[3])
#define MARGIN_i0
void SIM_hair_volume_grid_interpolate(HairGrid *grid, const float x[3], float *density, float velocity[3], float velocity_smooth[3], float density_gradient[3], float velocity_gradient[3][3])
BLI_INLINE int floor_int(float value)
Definition: hair_volume.cpp:40
#define NEIGHBOR_MARGIN_i1
#define NEIGHBOR_MARGIN_i0
BLI_INLINE int hair_grid_size(const int res[3])
Definition: hair_volume.cpp:50
static const float density_threshold
BLI_INLINE float dist_tent_v3f3(const float a[3], float x, float y, float z)
#define NEIGHBOR_MARGIN_j1
void SIM_hair_volume_grid_clear(HairGrid *grid)
#define NEIGHBOR_MARGIN_k1
BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3])
BLI_INLINE int hair_grid_weights(const int res[3], const float gmin[3], float scale, const float vec[3], float weights[8])
BLI_INLINE void hair_volume_eval_grid_vertex_sample(HairGridVert *vert, const float loc[3], float radius, float dist_scale, const float x[3], const float v[3])
BLI_INLINE float weights_sum(const float weights[8])
BLI_INLINE float floor_mod(float value)
Definition: hair_volume.cpp:45
#define MARGIN_k1
BLI_INLINE bool hair_grid_point_valid(const float vec[3], const float gmin[3], const float gmax[3])
static float I[3][3]
Definition: hair_volume.cpp:38
void SIM_hair_volume_grid_geometry(HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3])
void SIM_hair_volume_free_vertex_grid(HairGrid *grid)
BLI_INLINE float hair_volume_density_divergence(float density, float target_density, float strength)
#define MARGIN_j1
bool SIM_hair_volume_solve_divergence(HairGrid *grid, float, float target_density, float target_strength)
BLI_INLINE int hair_grid_offset(const float vec[3], const int res[3], const float gmin[3], float scale)
Definition: hair_volume.cpp:73
void SIM_hair_volume_add_vertex(HairGrid *grid, const float x[3], const float v[3])
BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, const int res[3], const float gmin[3], float scale, const float vec[3], float *density, float velocity[3], float vel_smooth[3], float density_gradient[3], float velocity_gradient[3][3])
void SIM_hair_volume_normalize_vertex_grid(HairGrid *grid)
void SIM_hair_volume_add_segment(HairGrid *grid, const float UNUSED(x1[3]), const float UNUSED(v1[3]), const float x2[3], const float v2[3], const float x3[3], const float v3[3], const float UNUSED(x4[3]), const float UNUSED(v4[3]), const float UNUSED(dir1[3]), const float UNUSED(dir2[3]), const float UNUSED(dir3[3]))
HairGrid * SIM_hair_volume_create_vertex_grid(float cellsize, const float gmin[3], const float gmax[3])
void SIM_hair_volume_vertex_grid_forces(HairGrid *grid, const float x[3], const float v[3], float smoothfac, float pressurefac, float minpressure, float f[3], float dfdx[3][3], float dfdv[3][3])
#define MAX_HAIR_GRID_RES
Definition: implicit.h:216
float lfVector[3]
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix ccl_global float int int int int ccl_global const float int int int int int int int int int int int int num_samples
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define B
#define floorf(x)
Definition: metal/compat.h:224
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
struct ClothSimSettings * sim_parms
float velocity_smooth[3]
Definition: hair_volume.cpp:60
float velocity[3]
Definition: hair_volume.cpp:57
float gmax[3]
Definition: hair_volume.cpp:66
float gmin[3]
Definition: hair_volume.cpp:66
HairGridVert * verts
Definition: hair_volume.cpp:64
float inv_cellsize
Definition: hair_volume.cpp:67
int res[3]
Definition: hair_volume.cpp:65
float cellsize
Definition: hair_volume.cpp:67
void * first
Definition: DNA_listBase.h:31
float co[3]