source: GTP/trunk/App/Demos/Illum/pathmap/Triangle.cpp @ 2197

Revision 2197, 5.8 KB checked in by szirmay, 17 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include "Triangle.hpp"
3
4Triangle::Triangle(const Vector* a, const Vector* b, const Vector* c, const Material* material)
5                :a(a),b(b),c(c)
6{
7        this->material = material;
8        // calculate normals
9        normal = ((*a) - (*b)) && ((*a) - (*c));
10        normal.normalize();
11
12        // pre-calculate values for intersection tests
13        float x = fabsf (normal.x);
14        float y = fabsf (normal.y);
15        float z = fabsf (normal.z);
16        dominantAxis = (x > y) ? ((x > z) ? X_DOMINANT : Z_DOMINANT) : ((y > z) ? Y_DOMINANT : Z_DOMINANT);
17       
18        hyperPlaneShiftOffset = normal * (*a);
19       
20        switch (dominantAxis) {
21        case X_DOMINANT:
22                d1 = b->z - a->z;
23                d2 = b->y - a->y;
24                d3 = c->z - b->z;
25                d4 = c->y - b->y;
26                d5 = a->z - c->z;
27                d6 = a->y - c->y;
28                break;
29        case Y_DOMINANT:
30                d1 = b->z - a->z;
31                d2 = b->x - a->x;
32                d3 = c->z - b->z;
33                d4 = c->x - b->x;
34                d5 = a->z - c->z;
35                d6 = a->x - c->x;               
36                break;
37        case Z_DOMINANT:
38                d1 = b->y - a->y;
39                d2 = b->x - a->x;
40                d3 = c->y - b->y;
41                d4 = c->x - b->x;
42                d5 = a->y - c->y;
43                d6 = a->x - c->x;                       
44                break;
45        }
46       
47        bbox.minPoint = *a;
48        bbox.minPoint <= *b;
49        bbox.minPoint <= *c;
50
51        bbox.maxPoint = *a;
52        bbox.maxPoint >= *b;
53        bbox.maxPoint >= *c;
54}
55
56bool Triangle::intersect (const Ray& ray, float& depth, float rayMin, float rayMax)
57{       
58        lastTestedRayId = ray.id;
59        lastTestedRayResult.isIntersect = false;
60
61        float cosa = normal * ray.dir;
62        if (cosa > -0.00001f)   // back facing triangle
63                return false;
64       
65        float originDistOnNormal = -(normal * ray.origin);
66        depth = (hyperPlaneShiftOffset + originDistOnNormal) / cosa;
67        if (depth < 0.0f)
68                return false;
69       
70        float s, t;
71        switch (dominantAxis)
72        {
73        case X_DOMINANT:
74                // project to YZ plane than
75                // test that tg (P2->P1) > tg (P2->pintersect),
76                // so if pintersect is on the wrong side, drop it
77                s = ray.origin.y + depth * ray.dir.y;
78                t = ray.origin.z + depth * ray.dir.z;
79               
80                if ((b->y - s) * (d1) < (b->z - t) * (d2))      // speed up: e->g store: (b->z - a->z)
81                        return false;
82                if ((c->y - s) * (d3) < (c->z - t) * (d4))
83                        return false;
84                if ((a->y - s) * (d5) < (a->z - t) * (d6))
85                        return false;
86
87                lastTestedRayResult.isIntersect = true;
88                lastTestedRayResult.material    = this->material;
89                lastTestedRayResult.normal              = this->normal;
90                lastTestedRayResult.depth                       = depth;
91                lastTestedRayResult.point = ray.origin + ray.dir * depth;
92                lastTestedRayResult.object = this;
93                return true;
94               
95        case Y_DOMINANT:
96                s = ray.origin.x + depth * ray.dir.x;
97                t = ray.origin.z + depth * ray.dir.z;
98
99                if ((b->x - s) * (d1) < (b->z - t) * (d2))
100                        return false;
101                if ((c->x - s) * (d3) < (c->z - t) * (d4))
102                        return false;
103                if ((a->x - s) * (d5) < (a->z - t) * (d6))
104                        return false;
105                lastTestedRayResult.isIntersect = true;
106                lastTestedRayResult.material    = this->material;
107                lastTestedRayResult.normal              = this->normal;
108                lastTestedRayResult.depth                       = depth;
109                lastTestedRayResult.point = ray.origin + ray.dir * depth;
110                lastTestedRayResult.object = this;
111                return true;
112               
113        case Z_DOMINANT:
114                s = ray.origin.x + depth * ray.dir.x;
115                t = ray.origin.y + depth * ray.dir.y;
116
117                if ((b->x - s) * (d1) < (b->y - t) * (d2))
118                        return false;
119                if ((c->x - s) * (d3) < (c->y - t) * (d4))
120                        return false;
121                if ((a->x - s) * (d5) < (a->y - t) * (d6))
122                        return false;
123                lastTestedRayResult.isIntersect = true;
124                lastTestedRayResult.material    = this->material;
125                lastTestedRayResult.normal              = this->normal;
126                lastTestedRayResult.depth               = depth;
127                lastTestedRayResult.point = ray.origin + ray.dir * depth;
128                lastTestedRayResult.object = this;
129                return true;
130        }
131        return false;
132}
133
134bool Triangle::intersectBackSide (const Ray& ray, float& depth, float rayMin, float rayMax)
135{       
136        lastTestedRayId = ray.id;
137        lastTestedRayResult.isIntersect = false;
138
139        float cosa = normal * ray.dir;
140        if (cosa < 0.00001f)    // front facing triangle
141                return false;
142       
143        float originDistOnNormal = normal * ray.origin;
144        depth = -(hyperPlaneShiftOffset + originDistOnNormal) / cosa;
145        if (depth < 0.0f)
146                return false;
147       
148        float s, t;
149        switch (dominantAxis)
150        {
151        case X_DOMINANT:
152                // project to YZ plane than
153                // test that tg (P2->P1) > tg (P2->pintersect),
154                // so if pintersect is on the wrong side, drop it
155                s = ray.origin.y + depth * ray.dir.y;
156                t = ray.origin.z + depth * ray.dir.z;
157               
158                if ((b->y - s) * (d1) < (b->z - t) * (d2))      // speed up: e->g store: (b->z - a->z)
159                        return false;
160                if ((c->y - s) * (d3) < (c->z - t) * (d4))
161                        return false;
162                if ((a->y - s) * (d5) < (a->z - t) * (d6))
163                        return false;
164
165                lastTestedRayResult.isIntersect = true;
166                lastTestedRayResult.material    = this->material;
167                lastTestedRayResult.normal              = this->normal;
168                lastTestedRayResult.depth                       = depth;
169                lastTestedRayResult.point = ray.origin + ray.dir * depth;
170                lastTestedRayResult.object = this;
171                return true;
172               
173        case Y_DOMINANT:
174                s = ray.origin.x + depth * ray.dir.x;
175                t = ray.origin.z + depth * ray.dir.z;
176
177                if ((b->x - s) * (d1) < (b->z - t) * (d2))
178                        return false;
179                if ((c->x - s) * (d3) < (c->z - t) * (d4))
180                        return false;
181                if ((a->x -s) * (d5) < (a->z - t) * (d6))
182                        return false;
183                lastTestedRayResult.isIntersect = true;
184                lastTestedRayResult.material    = this->material;
185                lastTestedRayResult.normal              = this->normal;
186                lastTestedRayResult.depth                       = depth;
187                lastTestedRayResult.point = ray.origin + ray.dir * depth;
188                lastTestedRayResult.object = this;
189                return true;
190               
191        case Z_DOMINANT:
192                s = ray.origin.x + depth * ray.dir.x;
193                t = ray.origin.y + depth * ray.dir.y;
194
195                if ((b->x - s) * (d1) < (b->y - t) * (d2))
196                        return false;
197                if ((c->x - s) * (d3) < (c->y - t) * (d4))
198                        return false;
199                if ((a->x - s) * (d5) < (a->y - t) * (d6))
200                        return false;
201                lastTestedRayResult.isIntersect = true;
202                lastTestedRayResult.material    = this->material;
203                lastTestedRayResult.normal              = this->normal;
204                lastTestedRayResult.depth               = depth;
205                lastTestedRayResult.point = ray.origin + ray.dir * depth;
206                lastTestedRayResult.object = this;
207                return true;
208        }
209        return false;
210}
Note: See TracBrowser for help on using the repository browser.