#ifndef __MESH_H__ #define __MESH_H__ #include "intersect.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 */ texture upper_bounds; texture lower_bounds; /* map to child nodes/triangles and the number of child nodes/triangles */ texture node_map; texture node_length; __device__ float3 make_float3(const float4 &a) { return make_float3(a.x, a.y, a.z); } __device__ int convert(int c) { if (c & 0x80) return (0xFFFFFF00 | c); else return c; } /* 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) { float3 lower_bound = make_float3(tex1Dfetch(lower_bounds, i)); float3 upper_bound = make_float3(tex1Dfetch(upper_bounds, i)); return intersect_box(origin, direction, lower_bound, upper_bound); } /* 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__ __noinline__ int intersect_mesh(const float3 &origin, const float3& direction, float &min_distance, int last_hit_triangle = -1) { int triangle_index = -1; float distance; if (!intersect_node(origin, direction, g_start_node)) return -1; int stack[STACK_SIZE]; int *head = &stack[0]; int *node = &stack[1]; int *tail = &stack[STACK_SIZE-1]; *node = g_start_node; int i; do { int first_child = tex1Dfetch(node_map, *node); int child_count = tex1Dfetch(node_length, *node); while (*node >= g_first_node && child_count == 1) { *node = first_child; first_child = tex1Dfetch(node_map, *node); child_count = tex1Dfetch(node_length, *node); } if (*node >= g_first_node) { for (i=0; i < child_count; i++) { if (intersect_node(origin, direction, first_child+i)) { *node = first_child+i; node++; } } node--; } else // node is a leaf { for (i=0; i < child_count; i++) { if (last_hit_triangle == first_child+i) continue; uint4 triangle_data = g_triangles[first_child+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 = first_child + i; min_distance = distance; continue; } if (distance < min_distance) { triangle_index = first_child + i; min_distance = distance; } } } // 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) { g_triangles = triangles; g_vertices = vertices; g_colors = colors; g_start_node = start_node; g_first_node = first_node; } __global__ void set_colors(unsigned int *colors) { g_colors = colors; } } // extern "c" #endif