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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PositiveUnitRandomVector()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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
UnitRandomVector()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
operator HPoint() const85 Point::operator HPoint() const	{ return HPoint(x, y, z, 0.0f); }
86 
Refract(const Point & eye,const Point & n,float refractindex,Point & refracted)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 
ProjectToPlane(const Plane & p)109 Point& Point::ProjectToPlane(const Plane& p)
110 {
111 	*this-= (p.d + (*this|p.n))*p.n;
112 	return *this;
113 }
114 
ProjectToScreen(float halfrenderwidth,float halfrenderheight,const Matrix4x4 & mat,HPoint & projected) const115 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 
SetNotUsed()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 
IsNotUsed() const136 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 
Mult(const Matrix3x3 & mat,const Point & a)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 
Mult2(const Matrix3x3 & mat1,const Point & a1,const Matrix3x3 & mat2,const Point & a2)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 
Mac(const Matrix3x3 & mat,const Point & a)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 
TransMult(const Matrix3x3 & mat,const Point & a)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 
Transform(const Point & r,const Matrix3x3 & rotpos,const Point & linpos)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 
InvTransform(const Point & r,const Matrix3x3 & rotpos,const Point & linpos)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 }
194