Spaces:
Sleeping
Sleeping
| /** Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. | |
| * NVIDIA CORPORATION and its licensors retain all intellectual property | |
| * and proprietary rights in and to this software, related documentation | |
| * and any modifications thereto. Any use, reproduction, disclosure or | |
| * distribution of this software and related documentation without an express | |
| * license agreement from NVIDIA CORPORATION is strictly prohibited. | |
| */ | |
| namespace wp | |
| { | |
| struct HashGrid | |
| { | |
| float cell_width; | |
| float cell_width_inv; | |
| int* point_cells{nullptr}; // cell id of a point | |
| int* point_ids{nullptr}; // index to original point | |
| int* cell_starts{nullptr}; // start index of a range of indices belonging to a cell, dim_x*dim_y*dim_z in length | |
| int* cell_ends{nullptr}; // end index of a range of indices belonging to a cell, dim_x*dim_y*dim_z in length | |
| int dim_x; | |
| int dim_y; | |
| int dim_z; | |
| int num_points; | |
| int max_points; | |
| void* context; | |
| }; | |
| // convert a virtual (world) cell coordinate to a physical one | |
| CUDA_CALLABLE inline int hash_grid_index(const HashGrid& grid, int x, int y, int z) | |
| { | |
| // offset to ensure positive coordinates (means grid dim should be less than 4096^3) | |
| const int origin = 1<<20; | |
| x += origin; | |
| y += origin; | |
| z += origin; | |
| assert(0 < x); | |
| assert(0 < y); | |
| assert(0 < z); | |
| // clamp in case any particles fall outside the guard region (-10^20 cell index) | |
| x = max(0, x); | |
| y = max(0, y); | |
| z = max(0, z); | |
| // compute physical cell (assume pow2 grid dims) | |
| // int cx = x & (grid.dim_x-1); | |
| // int cy = y & (grid.dim_y-1); | |
| // int cz = z & (grid.dim_z-1); | |
| // compute physical cell (arbitrary grid dims) | |
| int cx = x%grid.dim_x; | |
| int cy = y%grid.dim_y; | |
| int cz = z%grid.dim_z; | |
| return cz*(grid.dim_x*grid.dim_y) + cy*grid.dim_x + cx; | |
| } | |
| CUDA_CALLABLE inline int hash_grid_index(const HashGrid& grid, const vec3& p) | |
| { | |
| return hash_grid_index(grid, | |
| int(p[0]*grid.cell_width_inv), | |
| int(p[1]*grid.cell_width_inv), | |
| int(p[2]*grid.cell_width_inv)); | |
| } | |
| // stores state required to traverse neighboring cells of a point | |
| struct hash_grid_query_t | |
| { | |
| CUDA_CALLABLE hash_grid_query_t() {} | |
| CUDA_CALLABLE hash_grid_query_t(int) {} // for backward pass | |
| int x_start; | |
| int y_start; | |
| int z_start; | |
| int x_end; | |
| int y_end; | |
| int z_end; | |
| int x; | |
| int y; | |
| int z; | |
| int cell; | |
| int cell_index; // offset in the current cell (index into cell_indices) | |
| int cell_end; // index following the end of this cell | |
| int current; // index of the current iterator value | |
| HashGrid grid; | |
| }; | |
| CUDA_CALLABLE inline hash_grid_query_t hash_grid_query(uint64_t id, wp::vec3 pos, float radius) | |
| { | |
| hash_grid_query_t query; | |
| query.grid = *(const HashGrid*)(id); | |
| // convert coordinate to grid | |
| query.x_start = int((pos[0]-radius)*query.grid.cell_width_inv); | |
| query.y_start = int((pos[1]-radius)*query.grid.cell_width_inv); | |
| query.z_start = int((pos[2]-radius)*query.grid.cell_width_inv); | |
| // do not want to visit any cells more than once, so limit large radius offset to one pass over each dimension | |
| query.x_end = min(int((pos[0]+radius)*query.grid.cell_width_inv), query.x_start + query.grid.dim_x-1); | |
| query.y_end = min(int((pos[1]+radius)*query.grid.cell_width_inv), query.y_start + query.grid.dim_y-1); | |
| query.z_end = min(int((pos[2]+radius)*query.grid.cell_width_inv), query.z_start + query.grid.dim_z-1); | |
| query.x = query.x_start; | |
| query.y = query.y_start; | |
| query.z = query.z_start; | |
| const int cell = hash_grid_index(query.grid, query.x, query.y, query.z); | |
| query.cell_index = query.grid.cell_starts[cell]; | |
| query.cell_end = query.grid.cell_ends[cell]; | |
| return query; | |
| } | |
| CUDA_CALLABLE inline bool hash_grid_query_next(hash_grid_query_t& query, int& index) | |
| { | |
| const HashGrid& grid = query.grid; | |
| if (!grid.point_cells) | |
| return false; | |
| while (1) | |
| { | |
| if (query.cell_index < query.cell_end) | |
| { | |
| // write output index | |
| index = grid.point_ids[query.cell_index++]; | |
| return true; | |
| } | |
| else | |
| { | |
| query.x++; | |
| if (query.x > query.x_end) | |
| { | |
| query.x = query.x_start; | |
| query.y++; | |
| } | |
| if (query.y > query.y_end) | |
| { | |
| query.y = query.y_start; | |
| query.z++; | |
| } | |
| if (query.z > query.z_end) | |
| { | |
| // finished lookup grid | |
| return false; | |
| } | |
| // update cell pointers | |
| const int cell = hash_grid_index(grid, query.x, query.y, query.z); | |
| query.cell_index = grid.cell_starts[cell]; | |
| query.cell_end = grid.cell_ends[cell]; | |
| } | |
| } | |
| } | |
| CUDA_CALLABLE inline int iter_next(hash_grid_query_t& query) | |
| { | |
| return query.current; | |
| } | |
| CUDA_CALLABLE inline bool iter_cmp(hash_grid_query_t& query) | |
| { | |
| bool finished = hash_grid_query_next(query, query.current); | |
| return finished; | |
| } | |
| CUDA_CALLABLE inline hash_grid_query_t iter_reverse(const hash_grid_query_t& query) | |
| { | |
| // can't reverse grid queries, users should not rely on neighbor ordering | |
| return query; | |
| } | |
| CUDA_CALLABLE inline int hash_grid_point_id(uint64_t id, int& index) | |
| { | |
| const HashGrid* grid = (const HashGrid*)(id); | |
| if (grid->point_ids == nullptr) | |
| return -1; | |
| return grid->point_ids[index]; | |
| } | |
| CUDA_CALLABLE inline void adj_hash_grid_query(uint64_t id, wp::vec3 pos, float radius, uint64_t& adj_id, wp::vec3& adj_pos, float& adj_radius, hash_grid_query_t& adj_res) {} | |
| CUDA_CALLABLE inline void adj_hash_grid_query_next(hash_grid_query_t& query, int& index, hash_grid_query_t& adj_query, int& adj_index, bool& adj_res) {} | |
| CUDA_CALLABLE inline void adj_hash_grid_point_id(uint64_t id, int& index, uint64_t & adj_id, int& adj_index, int& adj_res) {} | |
| } // namespace wp | |