source: GTP/trunk/App/Demos/Vis/CHC_revisited/Vector3.cpp @ 2751

Revision 2751, 6.3 KB checked in by mattausch, 17 years ago (diff)
Line 
1#include "Matrix4x4.h"
2#include "Vector3.h"
3#include <float.h>
4
5
6
7namespace CHCDemo
8{
9
10// Given min a vector to minimize and a candidate vector, replace
11// elements of min whose corresponding elements in Candidate are
12// smaller.  This function is used for finding objects' bounds,
13// among other things.
14void Minimize(Vector3 &min, const Vector3 &Candidate)
15{
16        if (Candidate.x < min.x)
17                min.x = Candidate.x;
18        if (Candidate.y < min.y)
19                min.y = Candidate.y;
20        if (Candidate.z < min.z)
21                min.z = Candidate.z;
22}
23
24// Given min a vector to minimize and a candidate vector, replace
25// elements of min whose corresponding elements in Candidate are
26// larger.  This function is used for finding objects' bounds,
27// among other things.
28void Maximize(Vector3 &max, const Vector3 &Candidate)
29{
30        if (Candidate.x > max.x)
31                max.x = Candidate.x;
32        if (Candidate.y > max.y)
33                max.y = Candidate.y;
34        if (Candidate.z > max.z)
35                max.z = Candidate.z;
36}
37
38// Project the vector onto the YZ, XZ, or XY plane depending on which.
39// which      Coordinate plane to project onto
40// 0          YZ
41// 1          XZ
42// 2          XY
43// This function is used by the polygon intersection code.
44
45void Vector3::ExtractVerts(float *px, float *py, int which) const
46{
47        switch (which) {
48        case 0:
49                *px = y;
50                *py = z;
51                break;
52        case 1:
53                *px = x;
54                *py = z;
55                break;
56        case 2:
57                *px = x;
58                *py = y;
59                break;
60        }
61}
62
63// returns the axis, where the vector has the largest value
64int
65Vector3::DrivingAxis(void) const
66{
67        int axis = 0;
68        float val = fabs(x);
69
70        if (fabs(y) > val) {
71                val = fabs(y);
72                axis = 1;
73        }
74
75        if (fabs(z) > val)
76                axis = 2;
77
78        return axis;
79}
80
81// returns the axis, where the vector has the smallest value
82int
83Vector3::TinyAxis(void) const
84{
85        int axis = 0;
86        float val = fabs(x);
87
88        if (fabs(y) < val) {
89                val = fabs(y);
90                axis = 1;
91        }
92
93        if (fabs(z) < val)
94                axis = 2;
95
96        return axis;
97}
98
99
100// Construct a view vector ViewN, and the vector ViewU perpendicular
101// to ViewN and lying in the plane given by ViewNxUpl
102// the last vector of ortogonal system is ViewV, that is
103// perpendicular to both ViewN and ViewU.
104// |ViewN| = |ViewU| = |ViewV| = 1
105// The ViewN vector pierces the center of the synthesized image
106//     ViewU vector goes from the center image rightwards
107//     ViewV vector goes from the center image upwards
108void
109ViewVectors(const Vector3 &DirAt, const Vector3 &Viewer,
110                        const Vector3 &UpL, Vector3 &ViewV, Vector3 &ViewU,
111                        Vector3 &ViewN)
112{
113        Vector3 U, V, N;
114        Vector3 Up = Normalize(UpL);
115
116        N = -Normalize(DirAt);
117
118        V = Normalize(Up - DirAt);
119        V -= N * DotProd(V, N);
120        V = Normalize(V);
121        U = CrossProd(V, N);
122
123        ViewU = U; // rightwards
124        ViewV = V; // upwards
125        ViewN = -N; // forwards
126#ifdef GTP_DEBUG
127        const float eps = 1e-3f;
128        if (fabs(Magnitude(ViewU) - 1.0) > eps) {
129                Debug << "ViewU magnitude error= " << Magnitude(ViewU) << "\n";
130        }
131        if (fabs(Magnitude(ViewV) - 1.0) > eps) {
132                Debug << "ViewU magnitude error= " << Magnitude(ViewV) << "\n";
133        }
134        if (fabs(Magnitude(ViewN) - 1.0) > eps) {
135                Debug << "ViewU magnitude error= " << Magnitude(ViewN) << "\n";
136        }
137#endif // GTP_DEBUG
138
139        return;
140}
141
142// Given the intersection point `P', you have available normal `N'
143// of unit length. Let us suppose the incoming ray has direction `D'.
144// Then we can construct such two vectors `U' and `V' that
145// `U',`N', and `D' are coplanar, and `V' is perpendicular
146// to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
147// the orthonormal base in space R3.
148void
149TangentVectors(Vector3 &U,
150                           Vector3 &V, // output
151                           const Vector3 &normal, // input
152                           const Vector3 &dirIncoming)
153{
154#ifdef GTP_DEBUG
155        float d = Magnitude(normal);
156        if ( (d < 0.99) ||
157                (d > 1.01) ) {
158                        Debug << " The normal has not unit length = " << d << endl;
159        }
160        d = Magnitude(dirIncoming);
161        if ( (d < 0.99) ||
162                (d > 1.01) ) {
163                        Debug << " The incoming dir has not unit length = " << d << endl;
164        }
165#endif
166
167        V = CrossProd(normal, dirIncoming);
168
169        if (SqrMagnitude(V) < 1e-3) {
170                // the normal and dirIncoming are colinear
171                // we can/have to generate arbitrary perpendicular vector to normal.
172                if (fabs(normal.x) < 0.6)
173                        V.SetValue(0.0, -normal.z, normal.y);
174                else {
175                        if (fabs(normal.y) < 0.6)
176                                V.SetValue(-normal.z, 0.0, normal.x);
177                        else
178                                V.SetValue(-normal.y, normal.x, 0.0);
179                }
180        }
181        V = Normalize(V);
182
183        U = CrossProd(normal, V);
184#ifdef GTP_DEBUG
185        d = SqrMagnitude(U);
186        if ( (d < 0.99) ||
187                (d > 1.01) ) {
188                        Debug << "The size of U vector incorrect\n";
189        }
190#endif
191        return; 
192}
193
194
195Vector3 UniformRandomVector()
196{
197        float r1 = RandomValue(0.0f, 1.0f);
198        float r2 = RandomValue(0.0f, 1.0f);
199
200        return UniformRandomVector(r1, r2);
201}
202
203
204Vector3 UniformRandomVector(const float r1, const float r2)
205{
206        float cosTheta = 1.0f - 2*r1;
207        float sinTheta = sqrt(1 - sqrt(cosTheta));
208        float fi = 2.0f * M_PI * r2;
209
210        Vector3 dir(sinTheta*sin(fi), cosTheta, sinTheta * cos(fi));
211
212        return dir;
213}
214
215
216Vector3 CosineRandomVector(const Vector3 &normal)
217{
218        float r1, r2;
219
220        r1 = RandomValue(0.0f, 1.0f);
221        r2 = RandomValue(0.0f, 1.0f);
222
223        return CosineRandomVector(r1, r2, normal);
224}
225
226
227Vector3 CosineRandomVector(const float r1,
228                                                   const float r2,
229                                                   const Vector3 &normal)
230{
231        float theta = 2.0f * M_PI * r2;
232        float radius = sqrt(r1);
233
234        float x = radius * sin(theta);
235        float z = radius * cos(theta);
236        float y = sqrt(1.0f - x*x - z*z);
237
238        Vector3 dir(x, y, z);
239
240        //  return Normalize(dir);
241
242        Matrix4x4 m = RotationVectorsMatrix(normal, Vector3(0,1,0));
243
244        Matrix4x4 mi = Invert(m);
245
246        m = m * RotationVectorsMatrix(Vector3(0,1,0), Normalize(dir)) * mi;
247
248        return TransformNormal(m, normal);
249}
250
251
252Vector3 UniformRandomVector(const Vector3 &normal)
253{
254        float r1 = RandomValue(0.0f, 1.0f);
255        float r2 = RandomValue(0.0f, 1.0f);
256       
257        float cosTheta = 1.0f - r1;
258        float sinTheta = sqrt(1 - sqr(cosTheta));
259        float fi = 2.0f*M_PI*r2;
260
261        Vector3 dir(sinTheta*sin(fi),
262                cosTheta,
263                sinTheta*cos(fi));
264
265        Matrix4x4 m = RotationVectorsMatrix(normal, Vector3(0,1,0));
266        Matrix4x4 mi = Invert(m);
267
268        m = m*RotationVectorsMatrix(Vector3(0, 1, 0), Normalize(dir)) * mi;
269
270        return TransformNormal(m, normal);
271}
272
273
274bool Vector3::CheckValidity() const
275{
276#ifdef _WIN32
277        return !(_isnan(x) || _isnan(y) || _isnan(z));
278#else
279        return !(isnan(x) || isnan(y) || isnan(z));
280#endif 
281}
282
283}
Note: See TracBrowser for help on using the repository browser.