1 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2 | /** |
---|
3 | * Contains code for 3D vectors. |
---|
4 | * \file IcePoint.cpp |
---|
5 | * \author Pierre Terdiman |
---|
6 | * \date April, 4, 2000 |
---|
7 | */ |
---|
8 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
9 | |
---|
10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
11 | /** |
---|
12 | * 3D point. |
---|
13 | * |
---|
14 | * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". |
---|
15 | * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). |
---|
16 | * |
---|
17 | * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; |
---|
18 | * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: |
---|
19 | * |
---|
20 | * \code |
---|
21 | * Point P0,P1 = some 3D points; |
---|
22 | * Point Delta = P1 - P0; |
---|
23 | * \endcode |
---|
24 | * |
---|
25 | * This compiles fine, although you should have written: |
---|
26 | * |
---|
27 | * \code |
---|
28 | * Point P0,P1 = some 3D points; |
---|
29 | * Vector3 Delta = P1 - P0; |
---|
30 | * \endcode |
---|
31 | * |
---|
32 | * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake |
---|
33 | * from the author or something you don't get. |
---|
34 | * |
---|
35 | * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. |
---|
36 | * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. |
---|
37 | * |
---|
38 | * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store |
---|
39 | * your model's vertices and in most cases, you really want to use Points to save ram. |
---|
40 | * |
---|
41 | * \class Point |
---|
42 | * \author Pierre Terdiman |
---|
43 | * \version 1.0 |
---|
44 | */ |
---|
45 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
46 | |
---|
47 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
48 | // Precompiled Header |
---|
49 | #include "Stdafx.h" |
---|
50 | |
---|
51 | using namespace IceMaths; |
---|
52 | |
---|
53 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
54 | /** |
---|
55 | * Creates a positive unit random vector. |
---|
56 | * \return Self-reference |
---|
57 | */ |
---|
58 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
59 | Point& Point::PositiveUnitRandomVector() |
---|
60 | { |
---|
61 | x = UnitRandomFloat(); |
---|
62 | y = UnitRandomFloat(); |
---|
63 | z = UnitRandomFloat(); |
---|
64 | Normalize(); |
---|
65 | return *this; |
---|
66 | } |
---|
67 | |
---|
68 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
69 | /** |
---|
70 | * Creates a unit random vector. |
---|
71 | * \return Self-reference |
---|
72 | */ |
---|
73 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
74 | Point& Point::UnitRandomVector() |
---|
75 | { |
---|
76 | x = UnitRandomFloat() - 0.5f; |
---|
77 | y = UnitRandomFloat() - 0.5f; |
---|
78 | z = UnitRandomFloat() - 0.5f; |
---|
79 | Normalize(); |
---|
80 | return *this; |
---|
81 | } |
---|
82 | |
---|
83 | // Cast operator |
---|
84 | // WARNING: not inlined |
---|
85 | Point::operator HPoint() const { return HPoint(x, y, z, 0.0f); } |
---|
86 | |
---|
87 | Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted) |
---|
88 | { |
---|
89 | // Point EyePt = eye position |
---|
90 | // Point p = current vertex |
---|
91 | // Point n = vertex normal |
---|
92 | // Point rv = refracted vector |
---|
93 | // Eye vector - doesn't need to be normalized |
---|
94 | Point Env; |
---|
95 | Env.x = eye.x - x; |
---|
96 | Env.y = eye.y - y; |
---|
97 | Env.z = eye.z - z; |
---|
98 | |
---|
99 | float NDotE = n|Env; |
---|
100 | float NDotN = n|n; |
---|
101 | NDotE /= refractindex; |
---|
102 | |
---|
103 | // Refracted vector |
---|
104 | refracted = n*NDotE - Env*NDotN; |
---|
105 | |
---|
106 | return *this; |
---|
107 | } |
---|
108 | |
---|
109 | Point& Point::ProjectToPlane(const Plane& p) |
---|
110 | { |
---|
111 | *this-= (p.d + (*this|p.n))*p.n; |
---|
112 | return *this; |
---|
113 | } |
---|
114 | |
---|
115 | void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const |
---|
116 | { |
---|
117 | projected = HPoint(x, y, z, 1.0f) * mat; |
---|
118 | projected.w = 1.0f / projected.w; |
---|
119 | |
---|
120 | projected.x*=projected.w; |
---|
121 | projected.y*=projected.w; |
---|
122 | projected.z*=projected.w; |
---|
123 | |
---|
124 | projected.x *= halfrenderwidth; projected.x += halfrenderwidth; |
---|
125 | projected.y *= -halfrenderheight; projected.y += halfrenderheight; |
---|
126 | } |
---|
127 | |
---|
128 | void Point::SetNotUsed() |
---|
129 | { |
---|
130 | // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. |
---|
131 | IR(x) = 0xffffffff; |
---|
132 | IR(y) = 0xffffffff; |
---|
133 | IR(z) = 0xffffffff; |
---|
134 | } |
---|
135 | |
---|
136 | BOOL Point::IsNotUsed() const |
---|
137 | { |
---|
138 | if(IR(x)!=0xffffffff) return FALSE; |
---|
139 | if(IR(y)!=0xffffffff) return FALSE; |
---|
140 | if(IR(z)!=0xffffffff) return FALSE; |
---|
141 | return TRUE; |
---|
142 | } |
---|
143 | |
---|
144 | Point& Point::Mult(const Matrix3x3& mat, const Point& a) |
---|
145 | { |
---|
146 | x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; |
---|
147 | y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; |
---|
148 | z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; |
---|
149 | return *this; |
---|
150 | } |
---|
151 | |
---|
152 | Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2) |
---|
153 | { |
---|
154 | x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; |
---|
155 | y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; |
---|
156 | z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; |
---|
157 | return *this; |
---|
158 | } |
---|
159 | |
---|
160 | Point& Point::Mac(const Matrix3x3& mat, const Point& a) |
---|
161 | { |
---|
162 | x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; |
---|
163 | y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; |
---|
164 | z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; |
---|
165 | return *this; |
---|
166 | } |
---|
167 | |
---|
168 | Point& Point::TransMult(const Matrix3x3& mat, const Point& a) |
---|
169 | { |
---|
170 | x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; |
---|
171 | y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; |
---|
172 | z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; |
---|
173 | return *this; |
---|
174 | } |
---|
175 | |
---|
176 | Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) |
---|
177 | { |
---|
178 | x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; |
---|
179 | y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; |
---|
180 | z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; |
---|
181 | return *this; |
---|
182 | } |
---|
183 | |
---|
184 | Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos) |
---|
185 | { |
---|
186 | float sx = r.x - linpos.x; |
---|
187 | float sy = r.y - linpos.y; |
---|
188 | float sz = r.z - linpos.z; |
---|
189 | x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; |
---|
190 | y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; |
---|
191 | z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; |
---|
192 | return *this; |
---|
193 | } |
---|