source: GTP/trunk/Lib/Vis/Preprocessing/src/Triangle3.cpp @ 2542

Revision 2542, 5.1 KB checked in by mattausch, 17 years ago (diff)
Line 
1#include "Triangle3.h"
2#include "Ray.h"
3#include "AxisAlignedBox3.h"
4#include "Containers.h"
5#include "Polygon3.h"
6
7
8using namespace std;
9
10namespace GtpVisibilityPreprocessor {
11
12       
13Triangle3::Triangle3(const Vector3 &a, const Vector3 &b, const Vector3 &c)
14{
15        Init(a, b, c);
16}
17
18
19void Triangle3::Init(const Vector3 &a, const Vector3 &b, const Vector3 &c)
20{
21        mVertices[0] = a;
22        mVertices[1] = b;
23        mVertices[2] = c;
24}
25
26
27float Triangle3::GetSpatialAngle(const Vector3 &point) const
28{
29        return 0.0f;
30}
31
32
33int
34Triangle3::CastRay(const Ray &ray,
35                                   float &t,
36                                   const float nearestT,
37                                   Vector3 &normal) const
38{
39        //////////////
40        // specialised triangle ray casting version
41        // using ray-plane intersection
42       
43        // get triangle edge vectors and plane normal
44        const Vector3 u = mVertices[0] - mVertices[1];
45    const Vector3 v = mVertices[2] - mVertices[1];
46
47        // cross product
48    normal = Normalize(CrossProd(v, u));
49
50        // ray direction vector
51    const Vector3 dir = ray.GetDir();
52    const Vector3 w0 = ray.GetLoc() - mVertices[1];
53
54        // params to calc ray-plane intersect
55    const float a = -DotProd(normal, w0);
56    const float b = DotProd(normal, dir);
57
58        // check for division by zero
59        if (fabs(b) < Limits::Small)
60        {   
61                // ray is parallel to triangle plane
62        if (a == 0)
63                {
64                        // ray lies in triangle plane
65            return Ray::INTERSECTION_OUT_OF_LIMITS;
66                }
67        else
68                {
69                        // ray disjoint from plane
70                        return Ray::NO_INTERSECTION;
71                }
72    }
73
74    // distance from origin of ray to plane
75    t = a / b;
76
77    if (t <= Limits::Small) // ray goes away from triangle
78        {
79          return Ray::INTERSECTION_OUT_OF_LIMITS;
80        }
81        // already found nearer intersection
82        else if ((ray.GetType() == Ray::LOCAL_RAY) && (t >= nearestT))
83        {
84                return Ray::NO_INTERSECTION;
85        }
86
87        /////////////////
88    //-- found intersection point
89        //-- check if it is inside triangle
90 
91        const Vector3 pt = ray.GetLoc() + t * dir;
92#if GTP_DEBUG
93        if (!pt.CheckValidity())
94        {
95                cout << "tr: " << *this << endl;
96                cout << "v: " << pt << " t: " << t << " a: " << a << " b: " << b << " n: " << normal << endl;
97        }
98#endif
99        const Vector3 w = pt - mVertices[1];
100
101        const float uu = DotProd(u, u);
102    const float uv = DotProd(u, v);
103    const float vv = DotProd(v, v);
104   
105        const float wu = DotProd(w, u);
106    const float wv = DotProd(w, v);
107
108
109        const float D = uv * uv - uu * vv;
110
111    // get and test parametric coords
112    const float s = (uv * wv - vv * wu) / D;
113
114    if ((s < -Limits::Small) || (s > 1.0f + Limits::Small)) // pt is outside triangle
115        {       
116        return Ray::NO_INTERSECTION;
117        }
118
119        const float s2 = (uv * wu - uu * wv) / D;
120
121    if ((s2 < -Limits::Small) || ((s + s2) > 1.0f + Limits::Small)) // pt is outside triangle
122        {       
123        return Ray::NO_INTERSECTION;
124        }
125
126        return Ray::INTERSECTION; // I is in T
127}
128
129
130AxisAlignedBox3 Triangle3::GetBoundingBox() const
131{
132        AxisAlignedBox3 box;
133        box.Initialize();
134
135        box.Include(mVertices[0]);
136        box.Include(mVertices[1]);
137        box.Include(mVertices[2]);
138
139        return box;
140}
141
142
143Vector3 Triangle3::GetNormal() const
144{
145        const Vector3 v1 = mVertices[0] - mVertices[1];
146        const Vector3 v2 = mVertices[2] - mVertices[1];
147
148        return Normalize(CrossProd(v2, v1));
149}
150
151
152Vector3 Triangle3::GetCenter() const
153{
154        return (mVertices[0] + mVertices[1] + mVertices[2]) / 3.0f;
155}
156
157
158float Triangle3::GetArea() const
159{
160        Vector3 v1 = mVertices[0] - mVertices[1], v2=mVertices[2] - mVertices[1];
161        return 0.5f * Magnitude(CrossProd(v2, v1));
162}
163
164
165bool Triangle3::CheckValidity() const
166{
167        return !(
168                EpsilonEqualV3(mVertices[0], mVertices[1]) ||
169                EpsilonEqualV3(mVertices[0], mVertices[2]) ||
170                EpsilonEqualV3(mVertices[1], mVertices[2])
171                );
172}
173
174
175bool Triangle3::GetPlaneIntersection(const Plane3 &plane,
176                                                                         Vector3 &intersectA,
177                                                                         Vector3 &intersectB) const
178{
179        int side[3];
180
181        // compute distance from plane
182        for (int i = 0; i < 3; ++ i)
183        {
184                side[i] = plane.Side(mVertices[i], Limits::Small);
185        }
186
187        /////
188        // no intersection => early exit
189        if (((side[0] > 0) && (side[1] > 0) && (side[2] > 0)) ||
190                ((side[0] < 0) && (side[1] < 0) && (side[2] < 0)))
191        {
192                return false;
193        }
194
195        /////////////
196        // at least 2 triangle vertices lie in plane => early exit
197
198        for (int i = 0; i < 3; ++ i)
199        {
200                if (!side[i] && !side[(i + 1) % 3])
201                {
202                        intersectA = mVertices[i];
203                        intersectB = mVertices[(i + 1) % 3];
204                       
205                        return true;
206                }
207        }
208
209        bool foundA = false;
210
211        // compute intersection points
212        for (int i = 0; i < 3; ++ i)
213        {
214                const int i_2 = (i + 1) % 3;
215
216                // intersection found
217                if ((side[i] >= 0) && (side[i_2] <= 0) ||
218                        (side[i] <= 0) && (side[i_2] >= 0))
219                {       
220                        const float t = plane.FindT(mVertices[i], mVertices[i_2]);
221                       
222                        if (!foundA)
223                        {
224                                intersectA = mVertices[i] + t * (mVertices[i_2] - mVertices[i]);
225                       
226                                foundA = true;
227                        }
228                        else
229                        {
230                                intersectB = mVertices[i] + t * (mVertices[i_2] - mVertices[i]);
231                       
232                                return true;
233                        }
234                }
235        }
236
237        cout << "warning! wrong triangle - plane intersection" << endl;
238        return false; // something went wrong!
239}
240
241
242}
Note: See TracBrowser for help on using the repository browser.