diff options
Diffstat (limited to 'src/mesh.h')
-rw-r--r-- | src/mesh.h | 273 |
1 files changed, 125 insertions, 148 deletions
@@ -2,187 +2,164 @@ #define __MESH_H__ #include "intersect.h" +#include "geometry.h" #define STACK_SIZE 500 -/* flattened triangle mesh */ -__device__ float3 *g_vertices; -__device__ uint4 *g_triangles; -__device__ unsigned int *g_colors; -__device__ unsigned int g_start_node; -__device__ unsigned int g_first_node; - -/* lower/upper bounds for the bounding box associated with each node/leaf */ -__device__ float3 *g_lower_bounds; -__device__ float3 *g_upper_bounds; - -/* map to child node/triangle indices */ -texture<unsigned int, 1, cudaReadModeElementType> node_map; -texture<unsigned int, 1, cudaReadModeElementType> node_map_end; - -__device__ float3 make_float3(const float4 &a) +/* Tests the intersection between a ray and a node in the bounding volume + hierarchy. If the ray intersects the bounding volume and `min_distance` + is less than zero or the distance from `origin` to the intersection is + less than `min_distance`, return true, else return false. */ +__device__ bool +intersect_node(const float3 &origin, const float3 &direction, + Geometry *geometry, const int &i, const float &min_distance) { - return make_float3(a.x, a.y, a.z); -} + /* assigning these to local variables is faster for some reason */ + float3 lower_bound = geometry->lower_bounds[i]; + float3 upper_bound = geometry->upper_bounds[i]; -__device__ int convert(int c) -{ - if (c & 0x80) - return (0xFFFFFF00 | c); - else - return c; -} + float distance_to_box; -/* Test the intersection between a ray starting at `origin` traveling in the - direction `direction` and the bounding box around node `i`. If the ray - intersects the bounding box return true, else return false. */ -__device__ bool intersect_node(const float3 &origin, const float3 &direction, const int &i, const float &min_distance) -{ - float3 lower_bound = g_lower_bounds[i]; - float3 upper_bound = g_upper_bounds[i]; + if (intersect_box(origin, direction, lower_bound, upper_bound, + distance_to_box)) { + if (min_distance < 0.0f) + return true; - float distance_to_box; + if (distance_to_box > min_distance) + return false; - if (intersect_box(origin, direction, lower_bound, upper_bound, distance_to_box)) - { - if (min_distance < 0.0f) - return true; + return true; + } + else { + return false; + } - if (distance_to_box > min_distance) - return false; - - return true; - } - else - { - return false; - } - -} // intersect_node +} -/* Find the intersection between a ray starting at `origin` traveling in the - direction `direction` and the global mesh texture. If the ray intersects - the texture return the index of the triangle which the ray intersected, - else return -1. */ -__device__ int intersect_mesh(const float3 &origin, const float3& direction, float &min_distance, int last_hit_triangle = -1) +/* Finds the intersection between a ray and `geometry`. If the ray does + intersect the mesh and the index of the intersected triangle is not equal + to `last_hit_triangle`, set `min_distance` to the distance from `origin` to + the intersection and return the index of the triangle which the ray + intersected, else return -1. */ +__device__ int +intersect_mesh(const float3 &origin, const float3& direction, + Geometry *geometry, float &min_distance, + int last_hit_triangle = -1) { - int triangle_index = -1; + int triangle_index = -1; - float distance; - min_distance = -1.0f; + float distance; + min_distance = -1.0f; - if (!intersect_node(origin, direction, g_start_node, min_distance)) - return -1; + if (!intersect_node(origin, direction, geometry, geometry->start_node, + min_distance)) + return -1; - unsigned int stack[STACK_SIZE]; + unsigned int stack[STACK_SIZE]; - unsigned int *head = &stack[0]; - unsigned int *node = &stack[1]; - unsigned int *tail = &stack[STACK_SIZE-1]; - *node = g_start_node; + unsigned int *head = &stack[0]; + unsigned int *node = &stack[1]; + unsigned int *tail = &stack[STACK_SIZE-1]; + *node = geometry->start_node; - unsigned int i; + unsigned int i; - do - { - unsigned int first_child = tex1Dfetch(node_map, *node); - unsigned int stop = tex1Dfetch(node_map_end, *node); + do + { + unsigned int first_child = geometry->node_map[*node]; + unsigned int stop = geometry->node_map_end[*node]; - while (*node >= g_first_node && stop == first_child+1) - { - *node = first_child; - first_child = tex1Dfetch(node_map, *node); - stop = tex1Dfetch(node_map_end, *node); - } + while (*node >= geometry->first_node && stop == first_child+1) { + *node = first_child; + first_child = geometry->node_map[*node]; + stop = geometry->node_map_end[*node]; + } - if (*node >= g_first_node) - { - for (i=first_child; i < stop; i++) - { - if (intersect_node(origin, direction, i, min_distance)) - { - *node = i; - node++; - } - } - - node--; + if (*node >= geometry->first_node) { + for (i=first_child; i < stop; i++) { + if (intersect_node(origin, direction, geometry, i, + min_distance)) { + *node = i; + node++; + } + } + + node--; + } + else { + // node is a leaf + for (i=first_child; i < stop; i++) { + if (last_hit_triangle == i) + continue; + + Triangle triangle = get_triangle(geometry, i); + + if (intersect_triangle(origin, direction, triangle, + distance)) { + if (triangle_index == -1) { + triangle_index = i; + min_distance = distance; + continue; + } + + if (distance < min_distance) { + triangle_index = i; + min_distance = distance; + } } - else // node is a leaf - { - for (i=first_child; i < stop; i++) - { - if (last_hit_triangle == i) - continue; - - uint4 triangle_data = g_triangles[i]; - - float3 v0 = g_vertices[triangle_data.x]; - float3 v1 = g_vertices[triangle_data.y]; - float3 v2 = g_vertices[triangle_data.z]; - - if (intersect_triangle(origin, direction, v0, v1, v2, distance)) - { - if (triangle_index == -1) - { - triangle_index = i; - min_distance = distance; - continue; - } - - if (distance < min_distance) - { - triangle_index = i; - min_distance = distance; - } - } - } // triangle loop - - node--; - - } // node is a leaf - - } // while loop - while (node != head); - - return triangle_index; + } // triangle loop + + node--; + + } // node is a leaf + + } // while loop + while (node != head); + + return triangle_index; } extern "C" { -__global__ void set_global_mesh_variables(uint4 *triangles, float3 *vertices, unsigned int *colors, unsigned int start_node, unsigned int first_node, float3 *lower_bounds, float3 *upper_bounds) +__global__ void +distance_to_mesh(int nthreads, float3 *positions, float3 *directions, + Geometry *g, float *distances) { - g_triangles = triangles; - g_vertices = vertices; - g_colors = colors; - g_start_node = start_node; - g_first_node = first_node; - g_lower_bounds = lower_bounds; - g_upper_bounds = upper_bounds; -} + int id = blockIdx.x*blockDim.x + threadIdx.x; -__global__ void set_colors(unsigned int *colors) -{ - g_colors = colors; + if (id >= nthreads) + return; + + float3 position = positions[id]; + float3 direction = directions[id]; + direction /= norm(direction); + + float distance; + + int triangle_index = intersect_mesh(position, direction, g, distance); + + if (triangle_index == -1) + distances[id] = 1e9; + else + distances[id] = distance; } -__global__ void color_solids(int first_triangle, int nthreads, - int *solid_id_map, - bool *solid_hit, - unsigned int *solid_colors) +__global__ void +color_solids(int first_triangle, int nthreads, int *solid_id_map, + bool *solid_hit, unsigned int *solid_colors, Geometry *geometry) { - int id = blockIdx.x*blockDim.x + threadIdx.x; + int id = blockIdx.x*blockDim.x + threadIdx.x; - if (id >= nthreads) - return; + if (id >= nthreads) + return; - int triangle_id = first_triangle + id; - int solid_id = solid_id_map[triangle_id]; - if (solid_hit[solid_id]) - g_colors[triangle_id] = solid_colors[solid_id]; + int triangle_id = first_triangle + id; + int solid_id = solid_id_map[triangle_id]; + if (solid_hit[solid_id]) + geometry->colors[triangle_id] = solid_colors[solid_id]; } -} // extern "c" +} // extern "C" #endif |