| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							| 
									
										
										
										
											2020-11-06 01:41:31 -05:00
										 |  |  |  * \ingroup sim | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 20:29:51 +01:00
										 |  |  | #include "DNA_texture_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | #include "BKE_effect.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-08 18:45:28 +01:00
										 |  |  | #include "eigen_utils.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "implicit.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ================ Volumetric Hair Interaction ================
 | 
					
						
							|  |  |  |  * adapted from | 
					
						
							| 
									
										
										
										
											2018-06-01 18:19:39 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  |  * Volumetric Methods for Simulation and Rendering of Hair | 
					
						
							|  |  |  |  *     (Petrovic, Henne, Anderson, Pixar Technical Memo #06-08, Pixar Animation Studios) | 
					
						
							| 
									
										
										
										
											2018-06-01 18:19:39 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  |  * as well as | 
					
						
							| 
									
										
										
										
											2018-06-01 18:19:39 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  |  * "Detail Preserving Continuum Simulation of Straight Hair" | 
					
						
							|  |  |  |  *     (McAdams, Selle 2009) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Note about array indexing:
 | 
					
						
							|  |  |  |  * Generally the arrays here are one-dimensional. | 
					
						
							|  |  |  |  * The relation between 3D indices and the array offset is | 
					
						
							| 
									
										
										
										
											2014-11-06 15:08:25 +01:00
										 |  |  |  *   offset = x + res_x * y + res_x * res_y * z | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | BLI_INLINE int floor_int(float value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return value > 0.0f ? (int)value : ((int)value) - 1; | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BLI_INLINE float floor_mod(float value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return value - floorf(value); | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-06 14:05:32 +01:00
										 |  |  | BLI_INLINE int hair_grid_size(const int res[3]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return res[0] * res[1] * res[2]; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-09 16:29:11 +01:00
										 |  |  | struct HairGridVert { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int samples; | 
					
						
							|  |  |  |   float velocity[3]; | 
					
						
							|  |  |  |   float density; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float velocity_smooth[3]; | 
					
						
							| 
									
										
										
										
											2020-12-09 16:29:11 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-04 12:46:43 +01:00
										 |  |  | struct HairGrid { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   HairGridVert *verts; | 
					
						
							|  |  |  |   int res[3]; | 
					
						
							|  |  |  |   float gmin[3], gmax[3]; | 
					
						
							|  |  |  |   float cellsize, inv_cellsize; | 
					
						
							| 
									
										
										
										
											2020-12-04 12:46:43 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | #define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) \
 | 
					
						
							|  |  |  |   (min_ii(max_ii((int)((vec[axis] - gmin[axis]) * scale), 0), res[axis] - 2)) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | BLI_INLINE int hair_grid_offset(const float vec[3], | 
					
						
							|  |  |  |                                 const int res[3], | 
					
						
							|  |  |  |                                 const float gmin[3], | 
					
						
							|  |  |  |                                 float scale) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i, j, k; | 
					
						
							|  |  |  |   i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0); | 
					
						
							|  |  |  |   j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1); | 
					
						
							|  |  |  |   k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2); | 
					
						
							|  |  |  |   return i + (j + k * res[1]) * res[0]; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | BLI_INLINE int hair_grid_interp_weights( | 
					
						
							|  |  |  |     const int res[3], const float gmin[3], float scale, const float vec[3], float uvw[3]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i, j, k, offset; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0); | 
					
						
							|  |  |  |   j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1); | 
					
						
							|  |  |  |   k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2); | 
					
						
							|  |  |  |   offset = i + (j + k * res[1]) * res[0]; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uvw[0] = (vec[0] - gmin[0]) * scale - (float)i; | 
					
						
							|  |  |  |   uvw[1] = (vec[1] - gmin[1]) * scale - (float)j; | 
					
						
							|  |  |  |   uvw[2] = (vec[2] - gmin[2]) * scale - (float)k; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   //  BLI_assert(0.0f <= uvw[0] && uvw[0] <= 1.0001f);
 | 
					
						
							|  |  |  |   //  BLI_assert(0.0f <= uvw[1] && uvw[1] <= 1.0001f);
 | 
					
						
							|  |  |  |   //  BLI_assert(0.0f <= uvw[2] && uvw[2] <= 1.0001f);
 | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return offset; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   HairGridVert data[8]; | 
					
						
							|  |  |  |   float uvw[3], muvw[3]; | 
					
						
							|  |  |  |   int res2 = res[1] * res[0]; | 
					
						
							|  |  |  |   int offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   offset = hair_grid_interp_weights(res, gmin, scale, vec, uvw); | 
					
						
							|  |  |  |   muvw[0] = 1.0f - uvw[0]; | 
					
						
							|  |  |  |   muvw[1] = 1.0f - uvw[1]; | 
					
						
							|  |  |  |   muvw[2] = 1.0f - uvw[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data[0] = grid[offset]; | 
					
						
							|  |  |  |   data[1] = grid[offset + 1]; | 
					
						
							|  |  |  |   data[2] = grid[offset + res[0]]; | 
					
						
							|  |  |  |   data[3] = grid[offset + res[0] + 1]; | 
					
						
							|  |  |  |   data[4] = grid[offset + res2]; | 
					
						
							|  |  |  |   data[5] = grid[offset + res2 + 1]; | 
					
						
							|  |  |  |   data[6] = grid[offset + res2 + res[0]]; | 
					
						
							|  |  |  |   data[7] = grid[offset + res2 + res[0] + 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (density) { | 
					
						
							|  |  |  |     *density = muvw[2] * (muvw[1] * (muvw[0] * data[0].density + uvw[0] * data[1].density) + | 
					
						
							|  |  |  |                           uvw[1] * (muvw[0] * data[2].density + uvw[0] * data[3].density)) + | 
					
						
							|  |  |  |                uvw[2] * (muvw[1] * (muvw[0] * data[4].density + uvw[0] * data[5].density) + | 
					
						
							|  |  |  |                          uvw[1] * (muvw[0] * data[6].density + uvw[0] * data[7].density)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (velocity) { | 
					
						
							|  |  |  |     int k; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (k = 0; k < 3; k++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       velocity[k] = muvw[2] * | 
					
						
							|  |  |  |                         (muvw[1] * (muvw[0] * data[0].velocity[k] + uvw[0] * data[1].velocity[k]) + | 
					
						
							|  |  |  |                          uvw[1] * (muvw[0] * data[2].velocity[k] + uvw[0] * data[3].velocity[k])) + | 
					
						
							|  |  |  |                     uvw[2] * | 
					
						
							|  |  |  |                         (muvw[1] * (muvw[0] * data[4].velocity[k] + uvw[0] * data[5].velocity[k]) + | 
					
						
							|  |  |  |                          uvw[1] * (muvw[0] * data[6].velocity[k] + uvw[0] * data[7].velocity[k])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (vel_smooth) { | 
					
						
							|  |  |  |     int k; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (k = 0; k < 3; k++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       vel_smooth[k] = muvw[2] * (muvw[1] * (muvw[0] * data[0].velocity_smooth[k] + | 
					
						
							|  |  |  |                                             uvw[0] * data[1].velocity_smooth[k]) + | 
					
						
							|  |  |  |                                  uvw[1] * (muvw[0] * data[2].velocity_smooth[k] + | 
					
						
							|  |  |  |                                            uvw[0] * data[3].velocity_smooth[k])) + | 
					
						
							|  |  |  |                       uvw[2] * (muvw[1] * (muvw[0] * data[4].velocity_smooth[k] + | 
					
						
							|  |  |  |                                            uvw[0] * data[5].velocity_smooth[k]) + | 
					
						
							|  |  |  |                                 uvw[1] * (muvw[0] * data[6].velocity_smooth[k] + | 
					
						
							|  |  |  |                                           uvw[0] * data[7].velocity_smooth[k])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (density_gradient) { | 
					
						
							|  |  |  |     density_gradient[0] = muvw[1] * muvw[2] * (data[0].density - data[1].density) + | 
					
						
							|  |  |  |                           uvw[1] * muvw[2] * (data[2].density - data[3].density) + | 
					
						
							|  |  |  |                           muvw[1] * uvw[2] * (data[4].density - data[5].density) + | 
					
						
							|  |  |  |                           uvw[1] * uvw[2] * (data[6].density - data[7].density); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     density_gradient[1] = muvw[2] * muvw[0] * (data[0].density - data[2].density) + | 
					
						
							|  |  |  |                           uvw[2] * muvw[0] * (data[4].density - data[6].density) + | 
					
						
							|  |  |  |                           muvw[2] * uvw[0] * (data[1].density - data[3].density) + | 
					
						
							|  |  |  |                           uvw[2] * uvw[0] * (data[5].density - data[7].density); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     density_gradient[2] = muvw[2] * muvw[0] * (data[0].density - data[4].density) + | 
					
						
							|  |  |  |                           uvw[2] * muvw[0] * (data[1].density - data[5].density) + | 
					
						
							|  |  |  |                           muvw[2] * uvw[0] * (data[2].density - data[6].density) + | 
					
						
							|  |  |  |                           uvw[2] * uvw[0] * (data[3].density - data[7].density); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (velocity_gradient) { | 
					
						
							|  |  |  |     /* XXX TODO */ | 
					
						
							|  |  |  |     zero_m3(velocity_gradient); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_vertex_grid_forces(HairGrid *grid, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                         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]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float gdensity, gvelocity[3], ggrad[3], gvelgrad[3][3], gradlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   hair_grid_interpolate(grid->verts, | 
					
						
							|  |  |  |                         grid->res, | 
					
						
							|  |  |  |                         grid->gmin, | 
					
						
							|  |  |  |                         grid->inv_cellsize, | 
					
						
							|  |  |  |                         x, | 
					
						
							|  |  |  |                         &gdensity, | 
					
						
							|  |  |  |                         gvelocity, | 
					
						
							| 
									
										
										
										
											2020-11-06 17:49:09 +01:00
										 |  |  |                         nullptr, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                         ggrad, | 
					
						
							|  |  |  |                         gvelgrad); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   zero_v3(f); | 
					
						
							|  |  |  |   sub_v3_v3(gvelocity, v); | 
					
						
							|  |  |  |   mul_v3_v3fl(f, gvelocity, smoothfac); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   gradlen = normalize_v3(ggrad) - minpressure; | 
					
						
							|  |  |  |   if (gradlen > 0.0f) { | 
					
						
							|  |  |  |     mul_v3_fl(ggrad, gradlen); | 
					
						
							|  |  |  |     madd_v3_v3fl(f, ggrad, pressurefac); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   zero_m3(dfdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sub_m3_m3m3(dfdv, gvelgrad, I); | 
					
						
							|  |  |  |   mul_m3_fl(dfdv, smoothfac); | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_grid_interpolate(HairGrid *grid, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                       const float x[3], | 
					
						
							|  |  |  |                                       float *density, | 
					
						
							|  |  |  |                                       float velocity[3], | 
					
						
							|  |  |  |                                       float velocity_smooth[3], | 
					
						
							|  |  |  |                                       float density_gradient[3], | 
					
						
							|  |  |  |                                       float velocity_gradient[3][3]) | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   hair_grid_interpolate(grid->verts, | 
					
						
							|  |  |  |                         grid->res, | 
					
						
							|  |  |  |                         grid->gmin, | 
					
						
							|  |  |  |                         grid->inv_cellsize, | 
					
						
							|  |  |  |                         x, | 
					
						
							|  |  |  |                         density, | 
					
						
							|  |  |  |                         velocity, | 
					
						
							|  |  |  |                         velocity_smooth, | 
					
						
							|  |  |  |                         density_gradient, | 
					
						
							|  |  |  |                         velocity_gradient); | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_grid_velocity( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     HairGrid *grid, const float x[3], const float v[3], float fluid_factor, float r_v[3]) | 
					
						
							| 
									
										
										
										
											2014-10-31 11:59:14 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float gdensity, gvelocity[3], gvel_smooth[3], ggrad[3], gvelgrad[3][3]; | 
					
						
							|  |  |  |   float v_pic[3], v_flip[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   hair_grid_interpolate(grid->verts, | 
					
						
							|  |  |  |                         grid->res, | 
					
						
							|  |  |  |                         grid->gmin, | 
					
						
							|  |  |  |                         grid->inv_cellsize, | 
					
						
							|  |  |  |                         x, | 
					
						
							|  |  |  |                         &gdensity, | 
					
						
							|  |  |  |                         gvelocity, | 
					
						
							|  |  |  |                         gvel_smooth, | 
					
						
							|  |  |  |                         ggrad, | 
					
						
							|  |  |  |                         gvelgrad); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* velocity according to PIC method (Particle-in-Cell) */ | 
					
						
							|  |  |  |   copy_v3_v3(v_pic, gvel_smooth); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* velocity according to FLIP method (Fluid-Implicit-Particle) */ | 
					
						
							|  |  |  |   sub_v3_v3v3(v_flip, gvel_smooth, gvelocity); | 
					
						
							|  |  |  |   add_v3_v3(v_flip, v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   interp_v3_v3v3(r_v, v_pic, v_flip, fluid_factor); | 
					
						
							| 
									
										
										
										
											2014-11-08 18:45:28 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_grid_clear(HairGrid *grid) | 
					
						
							| 
									
										
										
										
											2014-11-08 18:45:28 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int size = hair_grid_size(grid->res); | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < size; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     zero_v3(grid->verts[i].velocity); | 
					
						
							|  |  |  |     zero_v3(grid->verts[i].velocity_smooth); | 
					
						
							|  |  |  |     grid->verts[i].density = 0.0f; | 
					
						
							|  |  |  |     grid->verts[i].samples = 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-10-31 11:59:14 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-13 11:27:09 +02:00
										 |  |  | BLI_INLINE bool hair_grid_point_valid(const float vec[3], const float gmin[3], const float gmax[3]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return !(vec[0] < gmin[0] || vec[1] < gmin[1] || vec[2] < gmin[2] || vec[0] > gmax[0] || | 
					
						
							|  |  |  |            vec[1] > gmax[1] || vec[2] > gmax[2]); | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BLI_INLINE float dist_tent_v3f3(const float a[3], float x, float y, float z) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float w = (1.0f - fabsf(a[0] - x)) * (1.0f - fabsf(a[1] - y)) * (1.0f - fabsf(a[2] - z)); | 
					
						
							|  |  |  |   return w; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  | BLI_INLINE float weights_sum(const float weights[8]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float totweight = 0.0f; | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < 8; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     totweight += weights[i]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return totweight; | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | /* returns the grid array offset as well to avoid redundant calculation */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | BLI_INLINE int hair_grid_weights( | 
					
						
							|  |  |  |     const int res[3], const float gmin[3], float scale, const float vec[3], float weights[8]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i, j, k, offset; | 
					
						
							|  |  |  |   float uvw[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0); | 
					
						
							|  |  |  |   j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1); | 
					
						
							|  |  |  |   k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2); | 
					
						
							|  |  |  |   offset = i + (j + k * res[1]) * res[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uvw[0] = (vec[0] - gmin[0]) * scale; | 
					
						
							|  |  |  |   uvw[1] = (vec[1] - gmin[1]) * scale; | 
					
						
							|  |  |  |   uvw[2] = (vec[2] - gmin[2]) * scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   weights[0] = dist_tent_v3f3(uvw, (float)i, (float)j, (float)k); | 
					
						
							|  |  |  |   weights[1] = dist_tent_v3f3(uvw, (float)(i + 1), (float)j, (float)k); | 
					
						
							|  |  |  |   weights[2] = dist_tent_v3f3(uvw, (float)i, (float)(j + 1), (float)k); | 
					
						
							|  |  |  |   weights[3] = dist_tent_v3f3(uvw, (float)(i + 1), (float)(j + 1), (float)k); | 
					
						
							|  |  |  |   weights[4] = dist_tent_v3f3(uvw, (float)i, (float)j, (float)(k + 1)); | 
					
						
							|  |  |  |   weights[5] = dist_tent_v3f3(uvw, (float)(i + 1), (float)j, (float)(k + 1)); | 
					
						
							|  |  |  |   weights[6] = dist_tent_v3f3(uvw, (float)i, (float)(j + 1), (float)(k + 1)); | 
					
						
							|  |  |  |   weights[7] = dist_tent_v3f3(uvw, (float)(i + 1), (float)(j + 1), (float)(k + 1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //  BLI_assert(fabsf(weights_sum(weights) - 1.0f) < 0.0001f);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return offset; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 14:41:55 +01:00
										 |  |  | BLI_INLINE void grid_to_world(HairGrid *grid, float vecw[3], const float vec[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_v3_v3(vecw, vec); | 
					
						
							|  |  |  |   mul_v3_fl(vecw, grid->cellsize); | 
					
						
							|  |  |  |   add_v3_v3(vecw, grid->gmin); | 
					
						
							| 
									
										
										
										
											2014-11-14 14:41:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_add_vertex(HairGrid *grid, const float x[3], const float v[3]) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int res[3] = {grid->res[0], grid->res[1], grid->res[2]}; | 
					
						
							|  |  |  |   float weights[8]; | 
					
						
							|  |  |  |   int di, dj, dk; | 
					
						
							|  |  |  |   int offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   if (!hair_grid_point_valid(x, grid->gmin, grid->gmax)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   offset = hair_grid_weights(res, grid->gmin, grid->inv_cellsize, x, weights); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (di = 0; di < 2; di++) { | 
					
						
							|  |  |  |     for (dj = 0; dj < 2; dj++) { | 
					
						
							|  |  |  |       for (dk = 0; dk < 2; dk++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         int voffset = offset + di + (dj + dk * res[1]) * res[0]; | 
					
						
							|  |  |  |         int iw = di + dj * 2 + dk * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         grid->verts[voffset].density += weights[iw]; | 
					
						
							|  |  |  |         madd_v3_v3fl(grid->verts[voffset].velocity, v, weights[iw]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  | BLI_INLINE void hair_volume_eval_grid_vertex(HairGridVert *vert, | 
					
						
							|  |  |  |                                              const float loc[3], | 
					
						
							|  |  |  |                                              float radius, | 
					
						
							|  |  |  |                                              float dist_scale, | 
					
						
							|  |  |  |                                              const float x2[3], | 
					
						
							|  |  |  |                                              const float v2[3], | 
					
						
							|  |  |  |                                              const float x3[3], | 
					
						
							|  |  |  |                                              const float v3[3]) | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float closest[3], lambda, dist, weight; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   lambda = closest_to_line_v3(closest, loc, x2, x3); | 
					
						
							|  |  |  |   dist = len_v3v3(closest, loc); | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   weight = (radius - dist) * dist_scale; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (weight > 0.0f) { | 
					
						
							|  |  |  |     float vel[3]; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     interp_v3_v3v3(vel, v2, v3, lambda); | 
					
						
							|  |  |  |     madd_v3_v3fl(vert->velocity, vel, weight); | 
					
						
							|  |  |  |     vert->density += weight; | 
					
						
							|  |  |  |     vert->samples += 1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BLI_INLINE int major_axis_v3(const float v[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float a = fabsf(v[0]); | 
					
						
							|  |  |  |   const float b = fabsf(v[1]); | 
					
						
							|  |  |  |   const float c = fabsf(v[2]); | 
					
						
							|  |  |  |   return a > b ? (a > c ? 0 : 2) : (b > c ? 1 : 2); | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  | BLI_INLINE void hair_volume_add_segment_2D(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 dir2[3], | 
					
						
							|  |  |  |                                            const float UNUSED(dir3[3]), | 
					
						
							|  |  |  |                                            int resj, | 
					
						
							|  |  |  |                                            int resk, | 
					
						
							|  |  |  |                                            int jmin, | 
					
						
							|  |  |  |                                            int jmax, | 
					
						
							|  |  |  |                                            int kmin, | 
					
						
							|  |  |  |                                            int kmax, | 
					
						
							|  |  |  |                                            HairGridVert *vert, | 
					
						
							|  |  |  |                                            int stride_j, | 
					
						
							|  |  |  |                                            int stride_k, | 
					
						
							|  |  |  |                                            const float loc[3], | 
					
						
							|  |  |  |                                            int axis_j, | 
					
						
							|  |  |  |                                            int axis_k, | 
					
						
							|  |  |  |                                            int debug_i) | 
					
						
							| 
									
										
										
										
											2014-11-13 16:01:36 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float radius = 1.5f; | 
					
						
							|  |  |  |   const float dist_scale = grid->inv_cellsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int j, k; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* boundary checks to be safe */ | 
					
						
							|  |  |  |   CLAMP_MIN(jmin, 0); | 
					
						
							|  |  |  |   CLAMP_MAX(jmax, resj - 1); | 
					
						
							|  |  |  |   CLAMP_MIN(kmin, 0); | 
					
						
							|  |  |  |   CLAMP_MAX(kmax, resk - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   HairGridVert *vert_j = vert + jmin * stride_j; | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   float loc_j[3] = {loc[0], loc[1], loc[2]}; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   loc_j[axis_j] += (float)jmin; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (j = jmin; j <= jmax; j++, vert_j += stride_j, loc_j[axis_j] += 1.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     HairGridVert *vert_k = vert_j + kmin * stride_k; | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |     float loc_k[3] = {loc_j[0], loc_j[1], loc_j[2]}; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     loc_k[axis_k] += (float)kmin; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (k = kmin; k <= kmax; k++, vert_k += stride_k, loc_k[axis_k] += 1.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       hair_volume_eval_grid_vertex(vert_k, loc_k, radius, dist_scale, x2, v2, x3, v3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if 0
 | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         float wloc[3], x2w[3], x3w[3]; | 
					
						
							|  |  |  |         grid_to_world(grid, wloc, loc_k); | 
					
						
							|  |  |  |         grid_to_world(grid, x2w, x2); | 
					
						
							|  |  |  |         grid_to_world(grid, x3w, x3); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |         if (vert_k->samples > 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           BKE_sim_debug_data_add_circle(wloc, 0.01f, 1.0, 1.0, 0.3, "grid", 2525, debug_i, j, k); | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (grid->debug_value) { | 
					
						
							|  |  |  |           BKE_sim_debug_data_add_dot(wloc, 1, 0, 0, "grid", 93, debug_i, j, k); | 
					
						
							|  |  |  |           BKE_sim_debug_data_add_dot(x2w, 0.1, 0.1, 0.7, "grid", 649, debug_i, j, k); | 
					
						
							|  |  |  |           BKE_sim_debug_data_add_line(wloc, x2w, 0.3, 0.8, 0.3, "grid", 253, debug_i, j, k); | 
					
						
							|  |  |  |           BKE_sim_debug_data_add_line(wloc, x3w, 0.8, 0.3, 0.3, "grid", 254, debug_i, j, k); | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |           // BKE_sim_debug_data_add_circle(
 | 
					
						
							|  |  |  |           //     x2w, len_v3v3(wloc, x2w), 0.2, 0.7, 0.2,
 | 
					
						
							|  |  |  |           //     "grid", 255, i, j, k);
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-13 16:01:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | /* Uses a variation of Bresenham's algorithm for rasterizing a 3D grid with a line segment.
 | 
					
						
							| 
									
										
										
										
											2018-06-01 18:19:39 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  |  * The radius of influence around a segment is assumed to be at most 2*cellsize, | 
					
						
							|  |  |  |  * i.e. only cells containing the segment and their direct neighbors are examined. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_add_segment(HairGrid *grid, | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |                                  const float x1[3], | 
					
						
							|  |  |  |                                  const float v1[3], | 
					
						
							|  |  |  |                                  const float x2[3], | 
					
						
							|  |  |  |                                  const float v2[3], | 
					
						
							|  |  |  |                                  const float x3[3], | 
					
						
							|  |  |  |                                  const float v3[3], | 
					
						
							|  |  |  |                                  const float x4[3], | 
					
						
							|  |  |  |                                  const float v4[3], | 
					
						
							|  |  |  |                                  const float dir1[3], | 
					
						
							|  |  |  |                                  const float dir2[3], | 
					
						
							|  |  |  |                                  const float dir3[3]) | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   const int res[3] = {grid->res[0], grid->res[1], grid->res[2]}; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* find the primary direction from the major axis of the direction vector */ | 
					
						
							|  |  |  |   const int axis0 = major_axis_v3(dir2); | 
					
						
							|  |  |  |   const int axis1 = (axis0 + 1) % 3; | 
					
						
							|  |  |  |   const int axis2 = (axis0 + 2) % 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* vertex buffer offset factors along cardinal axes */ | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   const int strides[3] = {1, res[0], res[0] * res[1]}; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int stride0 = strides[axis0]; | 
					
						
							|  |  |  |   const int stride1 = strides[axis1]; | 
					
						
							|  |  |  |   const int stride2 = strides[axis2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* increment of secondary directions per step in the primary direction
 | 
					
						
							|  |  |  |    * note: we always go in the positive direction along axis0, so the sign can be inverted | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   const float inc1 = dir2[axis1] / dir2[axis0]; | 
					
						
							|  |  |  |   const float inc2 = dir2[axis2] / dir2[axis0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* start/end points, so increment along axis0 is always positive */ | 
					
						
							|  |  |  |   const float *start = x2[axis0] < x3[axis0] ? x2 : x3; | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   const float *end = x2[axis0] < x3[axis0] ? x3 : x2; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float start0 = start[axis0], start1 = start[axis1], start2 = start[axis2]; | 
					
						
							|  |  |  |   const float end0 = end[axis0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* range along primary direction */ | 
					
						
							|  |  |  |   const int imin = max_ii(floor_int(start[axis0]) - 1, 0); | 
					
						
							|  |  |  |   const int imax = min_ii(floor_int(end[axis0]) + 2, res[axis0] - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float h = 0.0f; | 
					
						
							|  |  |  |   HairGridVert *vert0; | 
					
						
							|  |  |  |   float loc0[3]; | 
					
						
							|  |  |  |   int j0, k0, j0_prev, k0_prev; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = imin; i <= imax; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float shift1, shift2; /* fraction of a full cell shift [0.0, 1.0) */ | 
					
						
							|  |  |  |     int jmin, jmax, kmin, kmax; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     h = CLAMPIS((float)i, start0, end0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     shift1 = start1 + (h - start0) * inc1; | 
					
						
							|  |  |  |     shift2 = start2 + (h - start0) * inc2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     j0_prev = j0; | 
					
						
							|  |  |  |     j0 = floor_int(shift1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     k0_prev = k0; | 
					
						
							|  |  |  |     k0 = floor_int(shift2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i > imin) { | 
					
						
							|  |  |  |       jmin = min_ii(j0, j0_prev); | 
					
						
							|  |  |  |       jmax = max_ii(j0, j0_prev); | 
					
						
							|  |  |  |       kmin = min_ii(k0, k0_prev); | 
					
						
							|  |  |  |       kmax = max_ii(k0, k0_prev); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       jmin = jmax = j0; | 
					
						
							|  |  |  |       kmin = kmax = k0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vert0 = grid->verts + i * stride0; | 
					
						
							|  |  |  |     loc0[axis0] = (float)i; | 
					
						
							|  |  |  |     loc0[axis1] = 0.0f; | 
					
						
							|  |  |  |     loc0[axis2] = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |     hair_volume_add_segment_2D(grid, | 
					
						
							|  |  |  |                                x1, | 
					
						
							|  |  |  |                                v1, | 
					
						
							|  |  |  |                                x2, | 
					
						
							|  |  |  |                                v2, | 
					
						
							|  |  |  |                                x3, | 
					
						
							|  |  |  |                                v3, | 
					
						
							|  |  |  |                                x4, | 
					
						
							|  |  |  |                                v4, | 
					
						
							|  |  |  |                                dir1, | 
					
						
							|  |  |  |                                dir2, | 
					
						
							|  |  |  |                                dir3, | 
					
						
							|  |  |  |                                res[axis1], | 
					
						
							|  |  |  |                                res[axis2], | 
					
						
							|  |  |  |                                jmin - 1, | 
					
						
							|  |  |  |                                jmax + 2, | 
					
						
							|  |  |  |                                kmin - 1, | 
					
						
							|  |  |  |                                kmax + 2, | 
					
						
							|  |  |  |                                vert0, | 
					
						
							|  |  |  |                                stride1, | 
					
						
							|  |  |  |                                stride2, | 
					
						
							|  |  |  |                                loc0, | 
					
						
							|  |  |  |                                axis1, | 
					
						
							|  |  |  |                                axis2, | 
					
						
							|  |  |  |                                i); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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]) | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float dist, weight; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   dist = len_v3v3(x, loc); | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   weight = (radius - dist) * dist_scale; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (weight > 0.0f) { | 
					
						
							|  |  |  |     madd_v3_v3fl(vert->velocity, v, weight); | 
					
						
							|  |  |  |     vert->density += weight; | 
					
						
							|  |  |  |     vert->samples += 1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* XXX simplified test implementation using a series of discrete sample along the segment,
 | 
					
						
							|  |  |  |  * instead of finding the closest point for all affected grid vertices. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_add_segment(HairGrid *grid, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                  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])) | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float radius = 1.5f; | 
					
						
							|  |  |  |   const float dist_scale = grid->inv_cellsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const int res[3] = {grid->res[0], grid->res[1], grid->res[2]}; | 
					
						
							|  |  |  |   const int stride[3] = {1, res[0], res[0] * res[1]}; | 
					
						
							|  |  |  |   const int num_samples = 10; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (s = 0; s < num_samples; s++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float x[3], v[3]; | 
					
						
							|  |  |  |     int i, j, k; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     float f = (float)s / (float)(num_samples - 1); | 
					
						
							|  |  |  |     interp_v3_v3v3(x, x2, x3, f); | 
					
						
							|  |  |  |     interp_v3_v3v3(v, v2, v3, f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int imin = max_ii(floor_int(x[0]) - 2, 0); | 
					
						
							|  |  |  |     int imax = min_ii(floor_int(x[0]) + 2, res[0] - 1); | 
					
						
							|  |  |  |     int jmin = max_ii(floor_int(x[1]) - 2, 0); | 
					
						
							|  |  |  |     int jmax = min_ii(floor_int(x[1]) + 2, res[1] - 1); | 
					
						
							|  |  |  |     int kmin = max_ii(floor_int(x[2]) - 2, 0); | 
					
						
							|  |  |  |     int kmax = min_ii(floor_int(x[2]) + 2, res[2] - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (k = kmin; k <= kmax; k++) { | 
					
						
							|  |  |  |       for (j = jmin; j <= jmax; j++) { | 
					
						
							|  |  |  |         for (i = imin; i <= imax; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           float loc[3] = {(float)i, (float)j, (float)k}; | 
					
						
							|  |  |  |           HairGridVert *vert = grid->verts + i * stride[0] + j * stride[1] + k * stride[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           hair_volume_eval_grid_vertex_sample(vert, loc, radius, dist_scale, x, v); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-11-14 11:10:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-11-06 12:17:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_normalize_vertex_grid(HairGrid *grid) | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i, size = hair_grid_size(grid->res); | 
					
						
							|  |  |  |   /* divide velocity with density */ | 
					
						
							|  |  |  |   for (i = 0; i < size; i++) { | 
					
						
							|  |  |  |     float density = grid->verts[i].density; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |     if (density > 0.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       mul_v3_fl(grid->verts[i].velocity, 1.0f / density); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 22:17:22 +10:00
										 |  |  | /* Cells with density below this are considered empty. */ | 
					
						
							|  |  |  | static const float density_threshold = 0.001f; | 
					
						
							| 
									
										
										
										
											2014-11-13 16:06:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Contribution of target density pressure to the laplacian in the pressure poisson equation.
 | 
					
						
							|  |  |  |  * This is based on the model found in | 
					
						
							|  |  |  |  * "Two-way Coupled SPH and Particle Level Set Fluid Simulation" (Losasso et al., 2008) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | BLI_INLINE float hair_volume_density_divergence(float density, | 
					
						
							|  |  |  |                                                 float target_density, | 
					
						
							|  |  |  |                                                 float strength) | 
					
						
							| 
									
										
										
										
											2014-11-13 16:06:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   if (density > density_threshold && density > target_density) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return strength * logf(target_density / density); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 13:37:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return 0.0f; | 
					
						
							| 
									
										
										
										
											2014-11-13 16:06:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | bool SIM_hair_volume_solve_divergence(HairGrid *grid, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                       float /*dt*/, | 
					
						
							|  |  |  |                                       float target_density, | 
					
						
							|  |  |  |                                       float target_strength) | 
					
						
							| 
									
										
										
										
											2014-11-08 18:45:28 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float flowfac = grid->cellsize; | 
					
						
							|  |  |  |   const float inv_flowfac = 1.0f / grid->cellsize; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /*const int num_cells = hair_grid_size(grid->res);*/ | 
					
						
							|  |  |  |   const int res[3] = {grid->res[0], grid->res[1], grid->res[2]}; | 
					
						
							|  |  |  |   const int resA[3] = {grid->res[0] + 2, grid->res[1] + 2, grid->res[2] + 2}; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int stride0 = 1; | 
					
						
							|  |  |  |   const int stride1 = grid->res[0]; | 
					
						
							|  |  |  |   const int stride2 = grid->res[1] * grid->res[0]; | 
					
						
							|  |  |  |   const int strideA0 = 1; | 
					
						
							|  |  |  |   const int strideA1 = grid->res[0] + 2; | 
					
						
							|  |  |  |   const int strideA2 = (grid->res[1] + 2) * (grid->res[0] + 2); | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int num_cells = res[0] * res[1] * res[2]; | 
					
						
							|  |  |  |   const int num_cellsA = (res[0] + 2) * (res[1] + 2) * (res[2] + 2); | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   HairGridVert *vert_start = grid->verts - (stride0 + stride1 + stride2); | 
					
						
							|  |  |  |   HairGridVert *vert; | 
					
						
							|  |  |  |   int i, j, k; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-21 11:57:11 +11:00
										 |  |  | #define MARGIN_i0 (i < 1)
 | 
					
						
							|  |  |  | #define MARGIN_j0 (j < 1)
 | 
					
						
							|  |  |  | #define MARGIN_k0 (k < 1)
 | 
					
						
							| 
									
										
										
										
											2018-12-01 08:15:25 +11:00
										 |  |  | #define MARGIN_i1 (i >= resA[0] - 1)
 | 
					
						
							|  |  |  | #define MARGIN_j1 (j >= resA[1] - 1)
 | 
					
						
							|  |  |  | #define MARGIN_k1 (k >= resA[2] - 1)
 | 
					
						
							| 
									
										
										
										
											2015-01-21 11:57:11 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define NEIGHBOR_MARGIN_i0 (i < 2)
 | 
					
						
							|  |  |  | #define NEIGHBOR_MARGIN_j0 (j < 2)
 | 
					
						
							|  |  |  | #define NEIGHBOR_MARGIN_k0 (k < 2)
 | 
					
						
							| 
									
										
										
										
											2018-12-01 08:15:25 +11:00
										 |  |  | #define NEIGHBOR_MARGIN_i1 (i >= resA[0] - 2)
 | 
					
						
							|  |  |  | #define NEIGHBOR_MARGIN_j1 (j >= resA[1] - 2)
 | 
					
						
							|  |  |  | #define NEIGHBOR_MARGIN_k1 (k >= resA[2] - 2)
 | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_assert(num_cells >= 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Calculate divergence */ | 
					
						
							|  |  |  |   lVector B(num_cellsA); | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (k = 0; k < resA[2]; k++) { | 
					
						
							|  |  |  |     for (j = 0; j < resA[1]; j++) { | 
					
						
							|  |  |  |       for (i = 0; i < resA[0]; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         int u = i * strideA0 + j * strideA1 + k * strideA2; | 
					
						
							|  |  |  |         bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || | 
					
						
							|  |  |  |                          MARGIN_k1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_margin) { | 
					
						
							|  |  |  |           B[u] = 0.0f; | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vert = vert_start + i * stride0 + j * stride1 + k * stride2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const float *v0 = vert->velocity; | 
					
						
							|  |  |  |         float dx = 0.0f, dy = 0.0f, dz = 0.0f; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         if (!NEIGHBOR_MARGIN_i0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dx += v0[0] - (vert - stride0)->velocity[0]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (!NEIGHBOR_MARGIN_i1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dx += (vert + stride0)->velocity[0] - v0[0]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (!NEIGHBOR_MARGIN_j0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dy += v0[1] - (vert - stride1)->velocity[1]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (!NEIGHBOR_MARGIN_j1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dy += (vert + stride1)->velocity[1] - v0[1]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (!NEIGHBOR_MARGIN_k0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dz += v0[2] - (vert - stride2)->velocity[2]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (!NEIGHBOR_MARGIN_k1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           dz += (vert + stride2)->velocity[2] - v0[2]; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         float divergence = -0.5f * flowfac * (dx + dy + dz); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* adjustment term for target density */ | 
					
						
							|  |  |  |         float target = hair_volume_density_divergence( | 
					
						
							|  |  |  |             vert->density, target_density, target_strength); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* B vector contains the finite difference approximation of the velocity divergence.
 | 
					
						
							|  |  |  |          * Note: according to the discretized Navier-Stokes equation the rhs vector | 
					
						
							|  |  |  |          * and resulting pressure gradient should be multiplied by the (inverse) density; | 
					
						
							|  |  |  |          * however, this is already included in the weighting of hair velocities on the grid! | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         B[u] = divergence - target; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 14:45:46 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |           float wloc[3], loc[3]; | 
					
						
							|  |  |  |           float col0[3] = {0.0, 0.0, 0.0}; | 
					
						
							|  |  |  |           float colp[3] = {0.0, 1.0, 1.0}; | 
					
						
							|  |  |  |           float coln[3] = {1.0, 0.0, 1.0}; | 
					
						
							|  |  |  |           float col[3]; | 
					
						
							|  |  |  |           float fac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           loc[0] = (float)(i - 1); | 
					
						
							|  |  |  |           loc[1] = (float)(j - 1); | 
					
						
							|  |  |  |           loc[2] = (float)(k - 1); | 
					
						
							|  |  |  |           grid_to_world(grid, wloc, loc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (divergence > 0.0f) { | 
					
						
							|  |  |  |             fac = CLAMPIS(divergence * target_strength, 0.0, 1.0); | 
					
						
							|  |  |  |             interp_v3_v3v3(col, col0, colp, fac); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							|  |  |  |             fac = CLAMPIS(-divergence * target_strength, 0.0, 1.0); | 
					
						
							|  |  |  |             interp_v3_v3v3(col, col0, coln, fac); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |           if (fac > 0.05f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |             BKE_sim_debug_data_add_circle( | 
					
						
							|  |  |  |                 grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5522, i, j, k); | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-11-14 14:45:46 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Main Poisson equation system:
 | 
					
						
							|  |  |  |    * This is derived from the discretezation of the Poisson equation | 
					
						
							|  |  |  |    *   div(grad(p)) = div(v) | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The finite difference approximation yields the linear equation system described here: | 
					
						
							|  |  |  |    * https://en.wikipedia.org/wiki/Discrete_Poisson_equation
 | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   lMatrix A(num_cellsA, num_cellsA); | 
					
						
							|  |  |  |   /* Reserve space for the base equation system (without boundary conditions).
 | 
					
						
							|  |  |  |    * Each column contains a factor 6 on the diagonal | 
					
						
							|  |  |  |    * and up to 6 factors -1 on other places. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   A.reserve(Eigen::VectorXi::Constant(num_cellsA, 7)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (k = 0; k < resA[2]; k++) { | 
					
						
							|  |  |  |     for (j = 0; j < resA[1]; j++) { | 
					
						
							|  |  |  |       for (i = 0; i < resA[0]; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         int u = i * strideA0 + j * strideA1 + k * strideA2; | 
					
						
							|  |  |  |         bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || | 
					
						
							|  |  |  |                          MARGIN_k1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vert = vert_start + i * stride0 + j * stride1 + k * stride2; | 
					
						
							|  |  |  |         if (!is_margin && vert->density > density_threshold) { | 
					
						
							|  |  |  |           int neighbors_lo = 0; | 
					
						
							|  |  |  |           int neighbors_hi = 0; | 
					
						
							|  |  |  |           int non_solid_neighbors = 0; | 
					
						
							|  |  |  |           int neighbor_lo_index[3]; | 
					
						
							|  |  |  |           int neighbor_hi_index[3]; | 
					
						
							|  |  |  |           int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* check for upper bounds in advance
 | 
					
						
							|  |  |  |            * to get the correct number of neighbors, | 
					
						
							|  |  |  |            * needed for the diagonal element | 
					
						
							|  |  |  |            */ | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           if (!NEIGHBOR_MARGIN_k0 && (vert - stride2)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_lo_index[neighbors_lo++] = u - strideA2; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							|  |  |  |           if (!NEIGHBOR_MARGIN_j0 && (vert - stride1)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_lo_index[neighbors_lo++] = u - strideA1; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							|  |  |  |           if (!NEIGHBOR_MARGIN_i0 && (vert - stride0)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_lo_index[neighbors_lo++] = u - strideA0; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							|  |  |  |           if (!NEIGHBOR_MARGIN_i1 && (vert + stride0)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_hi_index[neighbors_hi++] = u + strideA0; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							|  |  |  |           if (!NEIGHBOR_MARGIN_j1 && (vert + stride1)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_hi_index[neighbors_hi++] = u + strideA1; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							|  |  |  |           if (!NEIGHBOR_MARGIN_k1 && (vert + stride2)->density > density_threshold) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             neighbor_hi_index[neighbors_hi++] = u + strideA2; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           /*int liquid_neighbors = neighbors_lo + neighbors_hi;*/ | 
					
						
							|  |  |  |           non_solid_neighbors = 6; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |           for (n = 0; n < neighbors_lo; n++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             A.insert(neighbor_lo_index[n], u) = -1.0f; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           A.insert(u, u) = (float)non_solid_neighbors; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |           for (n = 0; n < neighbors_hi; n++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             A.insert(neighbor_hi_index[n], u) = -1.0f; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           A.insert(u, u) = 1.0f; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ConjugateGradient cg; | 
					
						
							|  |  |  |   cg.setMaxIterations(100); | 
					
						
							|  |  |  |   cg.setTolerance(0.01f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   cg.compute(A); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   lVector p = cg.solve(B); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (cg.info() == Eigen::Success) { | 
					
						
							|  |  |  |     /* Calculate velocity = grad(p) */ | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (k = 0; k < resA[2]; k++) { | 
					
						
							|  |  |  |       for (j = 0; j < resA[1]; j++) { | 
					
						
							|  |  |  |         for (i = 0; i < resA[0]; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           int u = i * strideA0 + j * strideA1 + k * strideA2; | 
					
						
							|  |  |  |           bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || | 
					
						
							|  |  |  |                            MARGIN_k1; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           if (is_margin) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           vert = vert_start + i * stride0 + j * stride1 + k * stride2; | 
					
						
							|  |  |  |           if (vert->density > density_threshold) { | 
					
						
							|  |  |  |             float p_left = p[u - strideA0]; | 
					
						
							|  |  |  |             float p_right = p[u + strideA0]; | 
					
						
							|  |  |  |             float p_down = p[u - strideA1]; | 
					
						
							|  |  |  |             float p_up = p[u + strideA1]; | 
					
						
							|  |  |  |             float p_bottom = p[u - strideA2]; | 
					
						
							|  |  |  |             float p_top = p[u + strideA2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* finite difference estimate of pressure gradient */ | 
					
						
							|  |  |  |             float dvel[3]; | 
					
						
							|  |  |  |             dvel[0] = p_right - p_left; | 
					
						
							|  |  |  |             dvel[1] = p_up - p_down; | 
					
						
							|  |  |  |             dvel[2] = p_top - p_bottom; | 
					
						
							|  |  |  |             mul_v3_fl(dvel, -0.5f * inv_flowfac); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* pressure gradient describes velocity delta */ | 
					
						
							|  |  |  |             add_v3_v3v3(vert->velocity_smooth, vert->velocity, dvel); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							|  |  |  |             zero_v3(vert->velocity_smooth); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 14:45:46 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       int axis = 0; | 
					
						
							|  |  |  |       float offset = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       int slice = (offset - grid->gmin[axis]) / grid->cellsize; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |       for (k = 0; k < resA[2]; k++) { | 
					
						
							|  |  |  |         for (j = 0; j < resA[1]; j++) { | 
					
						
							|  |  |  |           for (i = 0; i < resA[0]; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             int u = i * strideA0 + j * strideA1 + k * strideA2; | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |             bool is_margin = MARGIN_i0 || MARGIN_i1 || MARGIN_j0 || MARGIN_j1 || MARGIN_k0 || | 
					
						
							|  |  |  |                              MARGIN_k1; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |             if (i != slice) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |               continue; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             vert = vert_start + i * stride0 + j * stride1 + k * stride2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             float wloc[3], loc[3]; | 
					
						
							|  |  |  |             float col0[3] = {0.0, 0.0, 0.0}; | 
					
						
							|  |  |  |             float colp[3] = {0.0, 1.0, 1.0}; | 
					
						
							|  |  |  |             float coln[3] = {1.0, 0.0, 1.0}; | 
					
						
							|  |  |  |             float col[3]; | 
					
						
							|  |  |  |             float fac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             loc[0] = (float)(i - 1); | 
					
						
							|  |  |  |             loc[1] = (float)(j - 1); | 
					
						
							|  |  |  |             loc[2] = (float)(k - 1); | 
					
						
							|  |  |  |             grid_to_world(grid, wloc, loc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             float pressure = p[u]; | 
					
						
							|  |  |  |             if (pressure > 0.0f) { | 
					
						
							|  |  |  |               fac = CLAMPIS(pressure * grid->debug1, 0.0, 1.0); | 
					
						
							|  |  |  |               interp_v3_v3v3(col, col0, colp, fac); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |               fac = CLAMPIS(-pressure * grid->debug1, 0.0, 1.0); | 
					
						
							|  |  |  |               interp_v3_v3v3(col, col0, coln, fac); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |             if (fac > 0.05f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |               BKE_sim_debug_data_add_circle( | 
					
						
							|  |  |  |                   grid->debug_data, wloc, 0.01f, col[0], col[1], col[2], "grid", 5533, i, j, k); | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (!is_margin) { | 
					
						
							|  |  |  |               float dvel[3]; | 
					
						
							|  |  |  |               sub_v3_v3v3(dvel, vert->velocity_smooth, vert->velocity); | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |               // BKE_sim_debug_data_add_vector(
 | 
					
						
							|  |  |  |               //     grid->debug_data, wloc, dvel, 1, 1, 1,
 | 
					
						
							|  |  |  |               //     "grid", 5566, i, j, k);
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!is_margin) { | 
					
						
							|  |  |  |               float d = CLAMPIS(vert->density * grid->debug2, 0.0f, 1.0f); | 
					
						
							|  |  |  |               float col0[3] = {0.3, 0.3, 0.3}; | 
					
						
							|  |  |  |               float colp[3] = {0.0, 0.0, 1.0}; | 
					
						
							|  |  |  |               float col[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               interp_v3_v3v3(col, col0, colp, d); | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |               // if (d > 0.05f) {
 | 
					
						
							|  |  |  |               // BKE_sim_debug_data_add_dot(
 | 
					
						
							|  |  |  |               //     grid->debug_data, wloc, col[0], col[1], col[2],
 | 
					
						
							|  |  |  |               //     "grid", 5544, i, j, k);
 | 
					
						
							|  |  |  |               // }
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-11-14 14:45:46 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 13:37:22 +02:00
										 |  |  |   /* Clear result in case of error */ | 
					
						
							|  |  |  |   for (i = 0, vert = grid->verts; i < num_cells; i++, vert++) { | 
					
						
							|  |  |  |     zero_v3(vert->velocity_smooth); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 13:37:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2014-11-08 18:45:28 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 09:24:31 +02:00
										 |  |  | #if 0 /* XXX weighting is incorrect, disabled for now */
 | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | /* Velocity filter kernel
 | 
					
						
							| 
									
										
										
										
											2016-10-25 17:32:58 +02:00
										 |  |  |  * See https://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29
 | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  | BLI_INLINE void hair_volume_filter_box_convolute( | 
					
						
							|  |  |  |     HairVertexGrid *grid, float invD, const int kernel_size[3], int i, int j, int k) | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int res = grid->res; | 
					
						
							|  |  |  |   int p, q, r; | 
					
						
							|  |  |  |   int minp = max_ii(i - kernel_size[0], 0), maxp = min_ii(i + kernel_size[0], res - 1); | 
					
						
							|  |  |  |   int minq = max_ii(j - kernel_size[1], 0), maxq = min_ii(j + kernel_size[1], res - 1); | 
					
						
							|  |  |  |   int minr = max_ii(k - kernel_size[2], 0), maxr = min_ii(k + kernel_size[2], res - 1); | 
					
						
							|  |  |  |   int offset, kernel_offset, kernel_dq, kernel_dr; | 
					
						
							|  |  |  |   HairGridVert *verts; | 
					
						
							|  |  |  |   float *vel_smooth; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   offset = i + (j + k * res) * res; | 
					
						
							|  |  |  |   verts = grid->verts; | 
					
						
							|  |  |  |   vel_smooth = verts[offset].velocity_smooth; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   kernel_offset = minp + (minq + minr * res) * res; | 
					
						
							|  |  |  |   kernel_dq = res; | 
					
						
							|  |  |  |   kernel_dr = res * res; | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (r = minr; r <= maxr; r++) { | 
					
						
							|  |  |  |     for (q = minq; q <= maxq; q++) { | 
					
						
							|  |  |  |       for (p = minp; p <= maxp; p++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         madd_v3_v3fl(vel_smooth, verts[kernel_offset].velocity, invD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kernel_offset += 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       kernel_offset += kernel_dq; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     kernel_offset += kernel_dr; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_vertex_grid_filter_box(HairVertexGrid *grid, int kernel_size) | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int size = hair_grid_size(grid->res); | 
					
						
							|  |  |  |   int kernel_sizev[3] = {kernel_size, kernel_size, kernel_size}; | 
					
						
							|  |  |  |   int tot; | 
					
						
							|  |  |  |   float invD; | 
					
						
							|  |  |  |   int i, j, k; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |   if (kernel_size <= 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   tot = kernel_size * 2 + 1; | 
					
						
							|  |  |  |   invD = 1.0f / (float)(tot * tot * tot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* clear values for convolution */ | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < size; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     zero_v3(grid->verts[i].velocity_smooth); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < grid->res; i++) { | 
					
						
							|  |  |  |     for (j = 0; j < grid->res; j++) { | 
					
						
							|  |  |  |       for (k = 0; k < grid->res; k++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         hair_volume_filter_box_convolute(grid, invD, kernel_sizev, i, j, k); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* apply as new velocity */ | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < size; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     copy_v3_v3(grid->verts[i].velocity, grid->verts[i].velocity_smooth); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-18 09:24:31 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-09-18 09:06:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | HairGrid *SIM_hair_volume_create_vertex_grid(float cellsize, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                              const float gmin[3], | 
					
						
							|  |  |  |                                              const float gmax[3]) | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float scale; | 
					
						
							|  |  |  |   float extent[3]; | 
					
						
							|  |  |  |   int resmin[3], resmax[3], res[3]; | 
					
						
							|  |  |  |   float gmin_margin[3], gmax_margin[3]; | 
					
						
							|  |  |  |   int size; | 
					
						
							|  |  |  |   HairGrid *grid; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* sanity check */ | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   if (cellsize <= 0.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     cellsize = 1.0f; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   scale = 1.0f / cellsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sub_v3_v3v3(extent, gmax, gmin); | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < 3; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     resmin[i] = floor_int(gmin[i] * scale); | 
					
						
							|  |  |  |     resmax[i] = floor_int(gmax[i] * scale) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* add margin of 1 cell */ | 
					
						
							|  |  |  |     resmin[i] -= 1; | 
					
						
							|  |  |  |     resmax[i] += 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res[i] = resmax[i] - resmin[i] + 1; | 
					
						
							|  |  |  |     /* sanity check: avoid null-sized grid */ | 
					
						
							|  |  |  |     if (res[i] < 4) { | 
					
						
							|  |  |  |       res[i] = 4; | 
					
						
							|  |  |  |       resmax[i] = resmin[i] + 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* sanity check: avoid too large grid size */ | 
					
						
							|  |  |  |     if (res[i] > MAX_HAIR_GRID_RES) { | 
					
						
							|  |  |  |       res[i] = MAX_HAIR_GRID_RES; | 
					
						
							|  |  |  |       resmax[i] = resmin[i] + MAX_HAIR_GRID_RES; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gmin_margin[i] = (float)resmin[i] * cellsize; | 
					
						
							|  |  |  |     gmax_margin[i] = (float)resmax[i] * cellsize; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   size = hair_grid_size(res); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   grid = (HairGrid *)MEM_callocN(sizeof(HairGrid), "hair grid"); | 
					
						
							|  |  |  |   grid->res[0] = res[0]; | 
					
						
							|  |  |  |   grid->res[1] = res[1]; | 
					
						
							|  |  |  |   grid->res[2] = res[2]; | 
					
						
							|  |  |  |   copy_v3_v3(grid->gmin, gmin_margin); | 
					
						
							|  |  |  |   copy_v3_v3(grid->gmax, gmax_margin); | 
					
						
							|  |  |  |   grid->cellsize = cellsize; | 
					
						
							|  |  |  |   grid->inv_cellsize = scale; | 
					
						
							|  |  |  |   grid->verts = (HairGridVert *)MEM_callocN(sizeof(HairGridVert) * size, "hair voxel data"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return grid; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_free_vertex_grid(HairGrid *grid) | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (grid) { | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |     if (grid->verts) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       MEM_freeN(grid->verts); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MEM_freeN(grid); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 14:37:21 +02:00
										 |  |  | void SIM_hair_volume_grid_geometry( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3]) | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   if (cellsize) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     *cellsize = grid->cellsize; | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (res) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     copy_v3_v3_int(res, grid->res); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (gmin) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     copy_v3_v3(gmin, grid->gmin); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (gmax) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     copy_v3_v3(gmax, grid->gmax); | 
					
						
							| 
									
										
										
										
											2019-05-31 22:51:19 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-10-31 14:23:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  | static HairGridVert *hair_volume_create_collision_grid(ClothModifierData *clmd, | 
					
						
							|  |  |  |                                                        lfVector *lX, | 
					
						
							|  |  |  |                                                        unsigned int numverts) | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int res = hair_grid_res; | 
					
						
							|  |  |  |   int size = hair_grid_size(res); | 
					
						
							|  |  |  |   HairGridVert *collgrid; | 
					
						
							|  |  |  |   ListBase *colliders; | 
					
						
							|  |  |  |   ColliderCache *col = NULL; | 
					
						
							|  |  |  |   float gmin[3], gmax[3], scale[3]; | 
					
						
							|  |  |  |   /* 2.0f is an experimental value that seems to give good results */ | 
					
						
							|  |  |  |   float collfac = 2.0f * clmd->sim_parms->collider_friction; | 
					
						
							|  |  |  |   unsigned int v = 0; | 
					
						
							|  |  |  |   int i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   hair_volume_get_boundbox(lX, numverts, gmin, gmax); | 
					
						
							|  |  |  |   hair_grid_get_scale(res, gmin, gmax, scale); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   collgrid = MEM_mallocN(sizeof(HairGridVert) * size, "hair collider voxel data"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* initialize grid */ | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |   for (i = 0; i < size; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     zero_v3(collgrid[i].velocity); | 
					
						
							|  |  |  |     collgrid[i].density = 0.0f; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* gather colliders */ | 
					
						
							|  |  |  |   colliders = BKE_collider_cache_create(depsgraph, NULL, NULL); | 
					
						
							|  |  |  |   if (colliders && collfac > 0.0f) { | 
					
						
							|  |  |  |     for (col = colliders->first; col; col = col->next) { | 
					
						
							|  |  |  |       MVert *loc0 = col->collmd->x; | 
					
						
							|  |  |  |       MVert *loc1 = col->collmd->xnew; | 
					
						
							|  |  |  |       float vel[3]; | 
					
						
							|  |  |  |       float weights[8]; | 
					
						
							|  |  |  |       int di, dj, dk; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (v = 0; v < col->collmd->numverts; v++, loc0++, loc1++) { | 
					
						
							|  |  |  |         int offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |         if (!hair_grid_point_valid(loc1->co, gmin, gmax)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           continue; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         offset = hair_grid_weights(res, gmin, scale, lX[v], weights); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sub_v3_v3v3(vel, loc1->co, loc0->co); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |         for (di = 0; di < 2; di++) { | 
					
						
							|  |  |  |           for (dj = 0; dj < 2; dj++) { | 
					
						
							|  |  |  |             for (dk = 0; dk < 2; dk++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |               int voffset = offset + di + (dj + dk * res) * res; | 
					
						
							|  |  |  |               int iw = di + dj * 2 + dk * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               collgrid[voffset].density += weights[iw]; | 
					
						
							|  |  |  |               madd_v3_v3fl(collgrid[voffset].velocity, vel, weights[iw]); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   BKE_collider_cache_free(&colliders); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* divide velocity with density */ | 
					
						
							|  |  |  |   for (i = 0; i < size; i++) { | 
					
						
							|  |  |  |     float density = collgrid[i].density; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |     if (density > 0.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       mul_v3_fl(collgrid[i].velocity, 1.0f / density); | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return collgrid; | 
					
						
							| 
									
										
										
										
											2014-09-14 18:08:14 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-16 20:44:25 +02:00
										 |  |  | #endif
 |