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

Revision 1420, 3.9 KB checked in by mattausch, 18 years ago (diff)

corrected raycasting bug for triangles because of ill defined triangles

Line 
1#include "Triangle3.h"
2#include "Ray.h"
3#include "AxisAlignedBox3.h"
4#include "Containers.h"
5#include "Polygon3.h"
6
7
8namespace GtpVisibilityPreprocessor {
9
10       
11Triangle3::Triangle3(const Vector3 &a, const Vector3 &b, const Vector3 &c)
12{
13        Init(a, b, c);
14}
15
16
17void Triangle3::Init(const Vector3 &a, const Vector3 &b, const Vector3 &c)
18{
19        mVertices[0] = a;
20        mVertices[1] = b;
21        mVertices[2] = c;
22}
23
24
25float Triangle3::GetSpatialAngle(const Vector3 &point) const
26{
27        return 0.0f;
28}
29
30
31int Triangle3::CastRay(const Ray &ray, float &t, const float nearestT, Vector3 &normal) const
32{
33#if 0
34        VertexContainer vertices;
35        vertices.push_back(mVertices[0]);
36        vertices.push_back(mVertices[1]);
37        vertices.push_back(mVertices[2]);
38
39        Polygon3 poly(vertices);
40       
41        int dummy = poly.CastRay(ray, t, nearestT);
42
43        cout << "polyversion code: " << dummy << " t: " << t << " nearestT: " << nearestT << endl;
44        return dummy;
45#endif
46       
47        //////////////
48        // specialised triangle ray casting version
49
50        ///////////
51        //-- calc ray-plane intersection
52       
53        // get triangle edge vectors and plane normal
54        const Vector3 u = mVertices[0] - mVertices[1];
55    const Vector3 v = mVertices[2] - mVertices[1];
56
57        // cross product
58    normal = Normalize(CrossProd(v, u));
59
60        // ray direction vector
61    const Vector3 dir = ray.GetDir();
62    const Vector3 w0 = ray.GetLoc() - mVertices[1];
63
64        // params to calc ray-plane intersect
65    const float a = -DotProd(normal, w0);
66    const float b = DotProd(normal, dir);
67
68        // check for division by zero
69        if (fabs(b) < Limits::Small)
70        {   
71                // ray is parallel to triangle plane
72        if (a == 0)
73                {
74                        // ray lies in triangle plane
75            return Ray::INTERSECTION_OUT_OF_LIMITS;
76                }
77        else
78                {
79                        // ray disjoint from plane
80                        return Ray::NO_INTERSECTION;
81                }
82    }
83
84    // distance from origin of ray to plane
85    t = a / b;
86
87    if (t < 0.0) // ray goes away from triangle
88        {
89                return Ray::NO_INTERSECTION; // => no intersect
90        }
91        // already found nearer intersection
92        else if ((ray.GetType() == Ray::LOCAL_RAY) && (t >= nearestT))
93        {
94                return Ray::NO_INTERSECTION;
95        }
96
97        /////////////////
98    //-- found intersection point
99        //-- check if it is inside triangle
100 
101        const Vector3 pt = ray.GetLoc() + t * dir;
102
103        if (!pt.CheckValidity())
104        {
105                cout << "tr: " << *this << endl;
106                cout << "v: " << pt << " t: " << t << " a: " << a << " b: " << b << " n: " << normal << endl;
107        }
108
109        const Vector3 w = pt - mVertices[1];
110
111        const float uu = DotProd(u, u);
112    const float uv = DotProd(u, v);
113    const float vv = DotProd(v, v);
114   
115        const float wu = DotProd(w, u);
116    const float wv = DotProd(w, v);
117    const float D = uv * uv - uu * vv;
118
119    // get and test parametric coords
120    const float s = (uv * wv - vv * wu) / D;
121
122    if ((s < 0.0) || (s > 1.0)) // pt is outside triangle
123        {       
124        return Ray::NO_INTERSECTION;
125        }
126
127        const float s2 = (uv * wu - uu * wv) / D;
128
129    if ((s2 < 0.0) || ((s + s2) > 1.0)) // pt is outside triangle
130        {       
131        return Ray::NO_INTERSECTION;
132        }
133
134        return Ray::INTERSECTION; // I is in T
135}
136
137
138AxisAlignedBox3 Triangle3::GetBoundingBox() const
139{
140        AxisAlignedBox3 box;
141        box.Initialize();
142
143        box.Include(mVertices[0]);
144        box.Include(mVertices[1]);
145        box.Include(mVertices[2]);
146
147        return box;
148}
149
150
151Vector3 Triangle3::GetNormal() const
152{
153        const Vector3 v1 = mVertices[0] - mVertices[1];
154        const Vector3 v2 = mVertices[2] - mVertices[1];
155
156        return Normalize(CrossProd(v2, v1));
157}
158
159
160Vector3 Triangle3::GetCenter() const
161{
162        return (mVertices[0] + mVertices[1] + mVertices[2]) / 3.0f;
163}
164
165
166float Triangle3::GetArea() const
167{
168        Vector3 v1 = mVertices[0] - mVertices[1], v2=mVertices[2] - mVertices[1];
169        return 0.5f * Magnitude(CrossProd(v2, v1));
170}
171
172
173bool Triangle3::CheckValidity() const
174{
175        return !(
176                EpsilonEqualV3(mVertices[0], mVertices[1]) ||
177                EpsilonEqualV3(mVertices[0], mVertices[2]) ||
178                EpsilonEqualV3(mVertices[1], mVertices[2])
179                );
180}
181
182}
Note: See TracBrowser for help on using the repository browser.