/* * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of NVIDIA CORPORATION nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "intersection_refinement.h" #include #include #include #include using namespace optix; // This is to be plugged into an RTgeometry object to represent // a triangle mesh with a vertex buffer of triangle soup (triangle list) // with an interleaved position, normal, texturecoordinate layout. rtBuffer vertex_buffer; rtBuffer normal_buffer; rtBuffer texcoord_buffer; rtBuffer index_buffer; rtBuffer material_buffer; rtDeclareVariable(float3, texcoord, attribute texcoord, ); rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, ); rtDeclareVariable(float3, shading_normal, attribute shading_normal, ); rtDeclareVariable(float3, back_hit_point, attribute back_hit_point, ); rtDeclareVariable(float3, front_hit_point, attribute front_hit_point, ); rtDeclareVariable(optix::Ray, ray, rtCurrentRay, ); template static __device__ void meshIntersect(int primIdx) { const int3 v_idx = index_buffer[primIdx]; const float3 p0 = vertex_buffer[v_idx.x]; const float3 p1 = vertex_buffer[v_idx.y]; const float3 p2 = vertex_buffer[v_idx.z]; // Intersect ray with triangle float3 n; float t, beta, gamma; if (intersect_triangle(ray, p0, p1, p2, n, t, beta, gamma)) { if (rtPotentialIntersection(t)) { geometric_normal = normalize(n); if (normal_buffer.size() == 0) { shading_normal = geometric_normal; } else { float3 n0 = normal_buffer[primIdx * 3]; float3 n1 = normal_buffer[primIdx * 3 + 1]; float3 n2 = normal_buffer[primIdx * 3 + 2]; shading_normal = normalize(n1 * beta + n2 * gamma + n0 * (1.0f - beta - gamma)); } if (texcoord_buffer.size() == 0) { texcoord = make_float3(0.0f, 0.0f, 0.0f); } else { float2 t0 = texcoord_buffer[primIdx * 3]; float2 t1 = texcoord_buffer[primIdx * 3 + 1]; float2 t2 = texcoord_buffer[primIdx * 3 + 2]; texcoord = make_float3(t1 * beta + t2 * gamma + t0 * (1.0f - beta - gamma)); } if (DO_REFINE) { refine_and_offset_hitpoint(ray.origin + t * ray.direction, ray.direction, geometric_normal, p0, back_hit_point, front_hit_point); } int material = 0; if (material_buffer.size() == 1) { material = material_buffer[0]; } else if (material_buffer.size() > 1) { material = material_buffer[primIdx]; } rtReportIntersection(material); } } } RT_PROGRAM void intersect(int primIdx) { meshIntersect(primIdx); } RT_PROGRAM void mesh_intersect_refine(int primIdx) { meshIntersect(primIdx); } RT_PROGRAM void bound(int primIdx, float result[6]) { const int3 v_idx = index_buffer[primIdx]; const float3 v0 = vertex_buffer[v_idx.x]; const float3 v1 = vertex_buffer[v_idx.y]; const float3 v2 = vertex_buffer[v_idx.z]; const float area = length(cross(v1 - v0, v2 - v0)); optix::Aabb* aabb = (optix::Aabb*)result; if (area > 0.0f && !isinf(area)) { aabb->m_min = fminf(fminf(v0, v1), v2); aabb->m_max = fmaxf(fmaxf(v0, v1), v2); } else { aabb->invalidate(); } }