Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
667 khor 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
7
#include "../CGLA/Vec4f.h"
8
#include "Triangle.h"
9
 
10
 
11
using namespace std;
12
using namespace CGLA;
13
 
14
namespace Geometry
15
{
16
 
17
const float EPSILON = 1e-10f;
18
 
19
Triangle::Triangle(const CGLA::Vec3f& _v0, 
20
									 const CGLA::Vec3f& _v1, 
21
									 const CGLA::Vec3f& _v2,
22
 
23
									 const CGLA::Vec3f& _vn0,
24
									 const CGLA::Vec3f& _vn1,
25
									 const CGLA::Vec3f& _vn2,
26
 
27
									 const CGLA::Vec3f& _en0,
28
									 const CGLA::Vec3f& _en1,
29
									 const CGLA::Vec3f& _en2)
30
{
31
	vert[0]  =_v0;
32
	vert[1]  =_v1;
33
	vert[2]  =_v2;
34
 
35
	vert_norm[0] = _vn0;
36
	vert_norm[1] = _vn1;
37
	vert_norm[2] = _vn2;
38
 
39
	edge_norm[0] = _en0;
40
	edge_norm[1] = _en1;
41
	edge_norm[2] = _en2;
42
 
43
	face_norm = normalize(cross(vert[1]-vert[0], vert[2]-vert[0]));
44
	for(int i=0;i<3;++i)
45
		{
46
			int j= (i+1)%3;
47
			edge[i] = vert[j]-vert[i];
48
			tri_plane_edge_norm[i] = cross(face_norm, edge[i]);
49
			edge_len[i] = edge[i].length();
50
		}
51
}
52
 
53
 
54
// Moellers method
55
bool Triangle::intersect(const CGLA::Vec3f& orig,
56
												 const CGLA::Vec3f& dir, float&t) const
57
{
58
	Vec3f tvec, pvec, qvec;
59
	float det,inv_det;
60
 
61
   /* begin calculating determinant - also used to calculate U parameter */
62
   pvec = cross(dir, -edge[2]);
63
 
64
   /* if determinant is near zero, ray lies in plane of triangle */
65
   det = dot(edge[0], pvec);
66
 
67
   if (det > -EPSILON && det < EPSILON)
68
     return 0;
69
   inv_det = 1.0 / det;
70
 
71
   /* calculate distance from v0 to ray origin */
72
   tvec =  orig - vert[0];
73
 
74
   /* calculate U parameter and test bounds */
75
   float u = dot(tvec, pvec) * inv_det;
76
   if (u < 0.0 || u > 1.0)
77
     return false;
78
 
79
   /* prepare to test V parameter */
80
   qvec = cross(tvec, edge[0]);
81
 
82
   /* calculate V parameter and test bounds */
83
   float v = dot(dir, qvec) * inv_det;
84
   if (v < 0.0 || u + v > 1.0)
85
     return false;
86
 
87
   /* calculate t, ray intersects triangle */
88
   t = dot(-edge[2], qvec) * inv_det;
89
 
90
   return true;
91
}
92
 
93
 
94
 
95
 
96
bool Triangle::signed_distance(const Vec3f& p, 
97
															 float& sq_dist, float& sgn) const
98
{
99
	int vertex_scores[3] = {0,0,0};
100
	Vec3f closest_pnt, normal;
101
	int idx_0;
102
 
103
	// Loop over all three edges.
104
	for(idx_0=0; idx_0<3; ++idx_0)
105
		{
106
			const int idx_1 = (idx_0+1) % 3;
107
			const Vec3f dir_3d = edge[idx_0]/edge_len[idx_0];
108
			const float t = dot(p - vert[idx_0], dir_3d);
109
			if(t <= 0)
110
				{
111
					++vertex_scores[idx_0];
112
					if(vertex_scores[idx_0] == 2)
113
						{
114
							closest_pnt = vert[idx_0];
115
							normal = vert_norm[idx_0];
116
							break;
117
						}
118
				}
119
			else if(t >= edge_len[idx_0])
120
				{
121
					++vertex_scores[idx_1];
122
					if(vertex_scores[idx_1] == 2)
123
						{
124
							closest_pnt = vert[idx_1];
125
							normal = vert_norm[idx_1];
126
							break;
127
						}
128
				}
129
			else if(dot(tri_plane_edge_norm[idx_0], p-vert[idx_0]) <=0)
130
				{
131
					closest_pnt=vert[idx_0]+t*dir_3d;
132
					normal = edge_norm[idx_0];
133
					break;
134
				}
135
		}
136
	if(idx_0 == 3)
137
		{
138
			closest_pnt = p - face_norm*(dot(p-vert[0],face_norm));
139
			normal = face_norm;
140
		}
141
	sq_dist = sqr_length(p-closest_pnt);
142
 
143
	// Compute dot product with angle weighted normal, and
144
	// assign the sign based on the result.
145
	if(dot(normal, p-closest_pnt) >=0)
146
		sgn = 1.0f;
147
	else
148
		sgn = -1.0f;
149
 
150
	return true;
151
}
152
 
153
}