forked from hkust-psan1/psan1-rendering-engine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
triangle_mesh_iterative.cu
136 lines (109 loc) · 5.04 KB
/
triangle_mesh_iterative.cu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Copyright (c) 2008 - 2009 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.
*
* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS*
* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
* INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY
* SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
* BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
* INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES
*/
#include <optix.h>
#include <optixu/optixu_math_namespace.h>
#include <optixu/optixu_matrix_namespace.h>
#include <optixu/optixu_aabb_namespace.h>
#include "intersection_refinement.h"
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.
rtDeclareVariable(unsigned int, thread_index, attribute thread_index, );
rtBuffer<float3> vertex_buffer;
rtBuffer<float3> normal_buffer;
rtBuffer<float2> texcoord_buffer;
rtBuffer<int3> vindex_buffer; // position indices
rtBuffer<int3> nindex_buffer; // normal indices
rtBuffer<int3> tindex_buffer; // texcoord indices
rtBuffer<uint> material_buffer; // per-face material index
rtDeclareVariable(float3, back_hit_point, attribute back_hit_point, );
rtDeclareVariable(float3, front_hit_point, attribute front_hit_point, );
rtDeclareVariable(float3, texcoord, attribute texcoord, );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
rtDeclareVariable(float3, tangent, attribute tangent, );
rtDeclareVariable(float3, bitangent, attribute bitangent, );
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
RT_PROGRAM void mesh_intersect( int primIdx )
{
// primIdx is the index to find the primitive (e.g. triangle in most cases)
// v_idx is the index to find the vertex data of that primitive (triangle)
int3 v_idx = vindex_buffer[primIdx];
thread_index = v_idx.x * v_idx.y * v_idx.z;
float3 p0 = vertex_buffer[ v_idx.x ];
float3 p1 = vertex_buffer[ v_idx.y ];
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 ) ) {
// Calculate normals and tex coords
float3 geo_n = normalize( n );
int3 n_idx = nindex_buffer[ primIdx ];
if ( normal_buffer.size() == 0 || n_idx.x < 0 || n_idx.y < 0 || n_idx.z < 0 ) {
shading_normal = geo_n;
} else {
float3 n0 = normal_buffer[ n_idx.x ];
float3 n1 = normal_buffer[ n_idx.y ];
float3 n2 = normal_buffer[ n_idx.z ];
shading_normal = normalize( n1*beta + n2*gamma + n0*(1.0f-beta-gamma) );
}
geometric_normal = geo_n;
int3 t_idx = tindex_buffer[ primIdx ];
if ( texcoord_buffer.size() == 0 || t_idx.x < 0 || t_idx.y < 0 || t_idx.z < 0 ) {
texcoord = make_float3( 0.0f, 0.0f, 0.0f );
} else {
float2 t0 = texcoord_buffer[ t_idx.x ];
float2 t1 = texcoord_buffer[ t_idx.y ];
float2 t2 = texcoord_buffer[ t_idx.z ];
// for tangent space calculations
float3 deltaP1 = p1 - p0;
float3 deltaP2 = p2 - p0;
float2 deltaT1 = t1 - t0;
float2 deltaT2 = t2 - t0;
float r = 1.0f / (deltaT1.x * deltaT2.y - deltaT1.y * deltaT2.x);
tangent = (deltaP1 * deltaT2.y - deltaP2 * deltaT1.y) * r;
bitangent = (deltaP2 * deltaT1.x - deltaP1 * deltaT2.x) * r;
texcoord = make_float3( t1*beta + t2*gamma + t0*(1.0f-beta-gamma) );
}
refine_and_offset_hitpoint( ray.origin + t*ray.direction, ray.direction,
geo_n, p0,
back_hit_point, front_hit_point );
rtReportIntersection(material_buffer[primIdx]);
}
}
}
RT_PROGRAM void mesh_bounds (int primIdx, float result[6])
{
const int3 v_idx = vindex_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();
}
}