sl@0
|
1 |
/*
|
sl@0
|
2 |
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
3 |
* All rights reserved.
|
sl@0
|
4 |
* This component and the accompanying materials are made available
|
sl@0
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
6 |
* which accompanies this distribution, and is available
|
sl@0
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
8 |
*
|
sl@0
|
9 |
* Initial Contributors:
|
sl@0
|
10 |
* Nokia Corporation - initial contribution.
|
sl@0
|
11 |
*
|
sl@0
|
12 |
* Contributors:
|
sl@0
|
13 |
*
|
sl@0
|
14 |
* Description: Vector and matrix math functions and data types
|
sl@0
|
15 |
*
|
sl@0
|
16 |
*/
|
sl@0
|
17 |
|
sl@0
|
18 |
#ifndef __M3G_MATH_H__
|
sl@0
|
19 |
#define __M3G_MATH_H__
|
sl@0
|
20 |
|
sl@0
|
21 |
/*!
|
sl@0
|
22 |
* \file
|
sl@0
|
23 |
* \brief Vector and matrix math functions and data types
|
sl@0
|
24 |
*/
|
sl@0
|
25 |
|
sl@0
|
26 |
/*----------------------------------------------------------------------
|
sl@0
|
27 |
* Internal data types
|
sl@0
|
28 |
*--------------------------------------------------------------------*/
|
sl@0
|
29 |
|
sl@0
|
30 |
/*!
|
sl@0
|
31 |
* \internal
|
sl@0
|
32 |
* \brief Axis-aligned bounding box
|
sl@0
|
33 |
*/
|
sl@0
|
34 |
typedef struct
|
sl@0
|
35 |
{
|
sl@0
|
36 |
M3Gfloat min[3], max[3];
|
sl@0
|
37 |
/*
|
sl@0
|
38 |
M3Gbyte min[3], minExp;
|
sl@0
|
39 |
M3Gbyte max[3], maxExp;
|
sl@0
|
40 |
*/
|
sl@0
|
41 |
} AABB;
|
sl@0
|
42 |
|
sl@0
|
43 |
/*----------------------------------------------------------------------
|
sl@0
|
44 |
* Global constants
|
sl@0
|
45 |
*--------------------------------------------------------------------*/
|
sl@0
|
46 |
|
sl@0
|
47 |
/*!
|
sl@0
|
48 |
* \internal
|
sl@0
|
49 |
* \brief Maximum positive float value
|
sl@0
|
50 |
*/
|
sl@0
|
51 |
#define M3G_MAX_POSITIVE_FLOAT (3.402e+38f)
|
sl@0
|
52 |
|
sl@0
|
53 |
/*!
|
sl@0
|
54 |
* \internal
|
sl@0
|
55 |
* \brief Minimum negative float value
|
sl@0
|
56 |
*/
|
sl@0
|
57 |
#define M3G_MIN_NEGATIVE_FLOAT (-3.402e+38f)
|
sl@0
|
58 |
|
sl@0
|
59 |
/*!
|
sl@0
|
60 |
* \internal
|
sl@0
|
61 |
* \brief Degrees to radians multiplier
|
sl@0
|
62 |
*/
|
sl@0
|
63 |
#define M3G_DEG2RAD (0.017453292519943295769236907684886f)
|
sl@0
|
64 |
|
sl@0
|
65 |
#define EPSILON (1.0e-5f)
|
sl@0
|
66 |
#define EPSILON_EXP (-17)
|
sl@0
|
67 |
#define RAD2DEG (57.295779513082320876798154814105f)
|
sl@0
|
68 |
#define PI (3.14159265359f)
|
sl@0
|
69 |
#define HALF_PI (PI / 2.0f)
|
sl@0
|
70 |
#define ONE_AND_HALF_PI (PI + HALF_PI)
|
sl@0
|
71 |
#define TWO_PI (2.f * PI)
|
sl@0
|
72 |
|
sl@0
|
73 |
/*! \internal \brief Extracts the bit pattern of a floating point number */
|
sl@0
|
74 |
#define FLOAT_AS_UINT(x) (*(M3Guint*)&(x))
|
sl@0
|
75 |
|
sl@0
|
76 |
/*! \internal \brief Returns an integer bit pattern as float */
|
sl@0
|
77 |
#define INT_AS_FLOAT(x) (*(M3Gfloat*)&(x))
|
sl@0
|
78 |
|
sl@0
|
79 |
/* IEEE floating point format */
|
sl@0
|
80 |
#define MANTISSA_MASK 0x007FFFFFu
|
sl@0
|
81 |
#define EXP_MASK 0x7F800000u
|
sl@0
|
82 |
#define SIGN_MASK 0x80000000u
|
sl@0
|
83 |
|
sl@0
|
84 |
#define M3G_FLOAT_ONE 0x3F800000
|
sl@0
|
85 |
|
sl@0
|
86 |
/*! \internal \brief Extracts the exponent of a floating point number */
|
sl@0
|
87 |
#define EXPONENT(x) (((M3Gint)(FLOAT_AS_UINT(x) & EXP_MASK) >> 23) - 127)
|
sl@0
|
88 |
|
sl@0
|
89 |
/*! \internal \brief Extracts the mantissa of a floating point number */
|
sl@0
|
90 |
#define MANTISSA(x) (FLOAT_AS_UINT(x) & MANTISSA_MASK)
|
sl@0
|
91 |
|
sl@0
|
92 |
/*! \internal \brief Extracts the sign of a floating point number */
|
sl@0
|
93 |
#define SIGN(x) (1 - ((FLOAT_AS_UINT(x) & SIGN_MASK) >> 30))
|
sl@0
|
94 |
|
sl@0
|
95 |
/*! \internal \brief Extracts just the sign bit of a floating point number */
|
sl@0
|
96 |
#define SIGN_BIT(x) (FLOAT_AS_UINT(x) >> 31)
|
sl@0
|
97 |
|
sl@0
|
98 |
/* Useful constants */
|
sl@0
|
99 |
#define LEADING_ONE (1 << 23)
|
sl@0
|
100 |
|
sl@0
|
101 |
/*! \internal \brief Checks the sign of a floating point number */
|
sl@0
|
102 |
#define IS_NEGATIVE(x) ((FLOAT_AS_UINT(x) & SIGN_MASK) != 0)
|
sl@0
|
103 |
|
sl@0
|
104 |
/* Floating-point constant identification macros */
|
sl@0
|
105 |
# define IS_ZERO(x) ((FLOAT_AS_UINT(x) & ~SIGN_MASK) <= 0x01000000)
|
sl@0
|
106 |
# define IS_ONE(x) (((x) > 1.0f - EPSILON) && ((x) < 1.0f + EPSILON))
|
sl@0
|
107 |
# define IS_MINUS_ONE(x) (((x) > -1.0f - EPSILON) && ((x) < -1.0f + EPSILON))
|
sl@0
|
108 |
|
sl@0
|
109 |
/* Elementary vectors */
|
sl@0
|
110 |
static const Vec4 Vec4_X_AXIS = {1, 0, 0, 0};
|
sl@0
|
111 |
static const Vec4 Vec4_Y_AXIS = {0, 1, 0, 0};
|
sl@0
|
112 |
static const Vec4 Vec4_Z_AXIS = {0, 0, 1, 0};
|
sl@0
|
113 |
static const Vec4 Vec4_ORIGIN = {0, 0, 0, 1};
|
sl@0
|
114 |
|
sl@0
|
115 |
/*----------------------------------------------------------------------
|
sl@0
|
116 |
* Elementary floating-point math
|
sl@0
|
117 |
*--------------------------------------------------------------------*/
|
sl@0
|
118 |
|
sl@0
|
119 |
#if defined(M3G_SOFT_FLOAT)
|
sl@0
|
120 |
static M3Gfloat m3gAdd(const M3Gfloat a, const M3Gfloat b);
|
sl@0
|
121 |
static M3Gfloat m3gMul(const M3Gfloat a, const M3Gfloat b);
|
sl@0
|
122 |
static M3Gfloat m3gRcpSqrt(const M3Gfloat x);
|
sl@0
|
123 |
static M3Gfloat m3gSqrt(const M3Gfloat x);
|
sl@0
|
124 |
static M3G_INLINE M3Gfloat m3gAbs(const M3Gfloat a)
|
sl@0
|
125 |
{
|
sl@0
|
126 |
M3Guint temp = FLOAT_AS_UINT(a) & ~SIGN_MASK;
|
sl@0
|
127 |
return INT_AS_FLOAT(temp);
|
sl@0
|
128 |
}
|
sl@0
|
129 |
static M3G_INLINE M3Gfloat m3gDiv(const M3Gfloat a, const M3Gfloat b)
|
sl@0
|
130 |
{
|
sl@0
|
131 |
return (a / b);
|
sl@0
|
132 |
}
|
sl@0
|
133 |
static M3G_INLINE M3Gfloat m3gDivif(const M3Gint a, const M3Gint b)
|
sl@0
|
134 |
{
|
sl@0
|
135 |
return m3gDiv((M3Gfloat) a, (M3Gfloat) b);
|
sl@0
|
136 |
}
|
sl@0
|
137 |
static M3G_INLINE M3Gfloat m3gMadd(const M3Gfloat a, const M3Gfloat b, const M3Gfloat c)
|
sl@0
|
138 |
{
|
sl@0
|
139 |
return m3gAdd(m3gMul(a, b), c);
|
sl@0
|
140 |
}
|
sl@0
|
141 |
static M3G_INLINE M3Gfloat m3gRcp(const M3Gfloat x)
|
sl@0
|
142 |
{
|
sl@0
|
143 |
return (1.0f / x);
|
sl@0
|
144 |
}
|
sl@0
|
145 |
static M3G_INLINE M3Gfloat m3gSub(const M3Gfloat a, const M3Gfloat b)
|
sl@0
|
146 |
{
|
sl@0
|
147 |
M3Guint bNeg = FLOAT_AS_UINT(b) ^ SIGN_MASK;
|
sl@0
|
148 |
return m3gAdd(a, INT_AS_FLOAT(bNeg));
|
sl@0
|
149 |
}
|
sl@0
|
150 |
#else
|
sl@0
|
151 |
# include <math.h>
|
sl@0
|
152 |
# define m3gAbs(a) ((float)fabs(a))
|
sl@0
|
153 |
# define m3gAdd(a, b) ((float)(a) + (float)(b))
|
sl@0
|
154 |
# define m3gMadd(a, b, c) ((float)(a) * (float)(b) + (float)(c))
|
sl@0
|
155 |
# define m3gMul(a, b) ((float)(a) * (float)(b))
|
sl@0
|
156 |
# define m3gDiv(a, b) ((float)(a) / (float)(b))
|
sl@0
|
157 |
# define m3gDivif(a, b) ((float)(a) / (float)(b))
|
sl@0
|
158 |
# define m3gRcp(x) (1.0f / (float)(x))
|
sl@0
|
159 |
# define m3gRcpSqrt(x) (1.0f / (float)sqrt(x))
|
sl@0
|
160 |
# define m3gSqrt(x) ((float)sqrt(x))
|
sl@0
|
161 |
# define m3gSub(a, b) ((float)(a) - (float)(b))
|
sl@0
|
162 |
#endif /* M3G_SOFT_FLOAT */
|
sl@0
|
163 |
|
sl@0
|
164 |
/*----------------------------------------------------------------------
|
sl@0
|
165 |
* Trigonometric and exp functions
|
sl@0
|
166 |
*--------------------------------------------------------------------*/
|
sl@0
|
167 |
|
sl@0
|
168 |
#if defined(M3G_SOFT_FLOAT)
|
sl@0
|
169 |
static M3Gfloat m3gArcCos(const M3Gfloat x);
|
sl@0
|
170 |
static M3Gfloat m3gArcTan(const M3Gfloat y, const M3Gfloat x);
|
sl@0
|
171 |
static M3Gfloat m3gCos(const M3Gfloat x);
|
sl@0
|
172 |
static M3Gfloat m3gSin(const M3Gfloat x);
|
sl@0
|
173 |
static M3Gfloat m3gTan(const M3Gfloat x);
|
sl@0
|
174 |
static M3Gfloat m3gExp(const M3Gfloat a);
|
sl@0
|
175 |
#else
|
sl@0
|
176 |
# define m3gArcCos(x) ((float)acos(x))
|
sl@0
|
177 |
# define m3gArcTan(y, x) ((float)atan2((y), (x)))
|
sl@0
|
178 |
# define m3gCos(x) ((float)cos(x))
|
sl@0
|
179 |
# define m3gSin(x) ((float)sin(x))
|
sl@0
|
180 |
# define m3gTan(x) ((float)tan(x))
|
sl@0
|
181 |
# define m3gExp(x) ((float)exp(x))
|
sl@0
|
182 |
#endif
|
sl@0
|
183 |
|
sl@0
|
184 |
/*----------------------------------------------------------------------
|
sl@0
|
185 |
* Matrix and quaternion stuff
|
sl@0
|
186 |
*--------------------------------------------------------------------*/
|
sl@0
|
187 |
|
sl@0
|
188 |
static M3Gbool m3gIsWUnity (const Matrix *mtx);
|
sl@0
|
189 |
|
sl@0
|
190 |
static void m3gExpQuat (Quat *quat, const Vec3 *qExp);
|
sl@0
|
191 |
static void m3gLogQuat (Vec3 *qLog, const Quat *quat);
|
sl@0
|
192 |
static void m3gLogDiffQuat (Vec3 *logDiff,
|
sl@0
|
193 |
const Quat *from, const Quat *to);
|
sl@0
|
194 |
static M3Gint m3gGetFixedPoint3x3Basis(const Matrix *mtx, M3Gshort *elem);
|
sl@0
|
195 |
static M3Gint m3gGetFixedPointTranslation(const Matrix *mtx, M3Gshort *elem);
|
sl@0
|
196 |
|
sl@0
|
197 |
/*----------------------------------------------------------------------
|
sl@0
|
198 |
* Bounding boxes
|
sl@0
|
199 |
*--------------------------------------------------------------------*/
|
sl@0
|
200 |
|
sl@0
|
201 |
static void m3gFitAABB(AABB *box, const AABB *a, const AABB *b);
|
sl@0
|
202 |
static void m3gTransformAABB(AABB *box, const Matrix *mtx);
|
sl@0
|
203 |
#if defined(M3G_DEBUG)
|
sl@0
|
204 |
static void m3gValidateAABB(const AABB *aabb);
|
sl@0
|
205 |
#else
|
sl@0
|
206 |
# define m3gValidateAABB(a)
|
sl@0
|
207 |
#endif
|
sl@0
|
208 |
|
sl@0
|
209 |
/*----------------------------------------------------------------------
|
sl@0
|
210 |
* Rounding and conversion
|
sl@0
|
211 |
*--------------------------------------------------------------------*/
|
sl@0
|
212 |
|
sl@0
|
213 |
static M3Gint m3gRoundToInt(const M3Gfloat a);
|
sl@0
|
214 |
|
sl@0
|
215 |
static M3Guint m3gAlpha1f(M3Gfloat a);
|
sl@0
|
216 |
/*static M3Guint m3gColor1f(M3Gfloat i);*/
|
sl@0
|
217 |
static M3Guint m3gColor3f(M3Gfloat r, M3Gfloat g, M3Gfloat b);
|
sl@0
|
218 |
static M3Guint m3gColor4f(M3Gfloat r, M3Gfloat g, M3Gfloat b, M3Gfloat a);
|
sl@0
|
219 |
static void m3gFloatColor(M3Gint argb, M3Gfloat intensity, M3Gfloat *rgba);
|
sl@0
|
220 |
|
sl@0
|
221 |
static M3Gbool m3gIntersectTriangle(const Vec3 *orig, const Vec3 *dir,
|
sl@0
|
222 |
const Vec3 *vert0, const Vec3 *vert1, const Vec3 *vert2,
|
sl@0
|
223 |
Vec3 *tuv, M3Gint cullMode);
|
sl@0
|
224 |
static M3Gbool m3gIntersectBox(const Vec3 *orig, const Vec3 *dir, const AABB *box);
|
sl@0
|
225 |
static M3Gbool m3gIntersectRectangle(M3GRectangle *dst, M3GRectangle *r1, M3GRectangle *r2);
|
sl@0
|
226 |
|
sl@0
|
227 |
/*----------------------------------------------------------------------
|
sl@0
|
228 |
* Inline functions
|
sl@0
|
229 |
*--------------------------------------------------------------------*/
|
sl@0
|
230 |
|
sl@0
|
231 |
/*!
|
sl@0
|
232 |
* \internal
|
sl@0
|
233 |
* \brief Multiplies a floating point number by 0.5.
|
sl@0
|
234 |
*
|
sl@0
|
235 |
* \param x the number to multiply
|
sl@0
|
236 |
* \return 0.5 * \c x
|
sl@0
|
237 |
*/
|
sl@0
|
238 |
static M3G_INLINE M3Gfloat m3gHalf(M3Gfloat x)
|
sl@0
|
239 |
{
|
sl@0
|
240 |
M3Guint bits = FLOAT_AS_UINT(x);
|
sl@0
|
241 |
M3Guint mask = 0xff;
|
sl@0
|
242 |
M3Gint exponent = bits & (mask << 23);
|
sl@0
|
243 |
bits ^= exponent;
|
sl@0
|
244 |
exponent = exponent - (1 << 23);
|
sl@0
|
245 |
if (exponent > 0) bits |= exponent;
|
sl@0
|
246 |
return INT_AS_FLOAT(bits);
|
sl@0
|
247 |
}
|
sl@0
|
248 |
|
sl@0
|
249 |
/*!
|
sl@0
|
250 |
* \internal
|
sl@0
|
251 |
* \brief Multiplies a floating point number by two
|
sl@0
|
252 |
*
|
sl@0
|
253 |
* This does NOT handle overflows.
|
sl@0
|
254 |
*
|
sl@0
|
255 |
* \param x the number to multiply
|
sl@0
|
256 |
* \return 2 * \c x
|
sl@0
|
257 |
*/
|
sl@0
|
258 |
static M3G_INLINE M3Gfloat m3gDouble(M3Gfloat x)
|
sl@0
|
259 |
{
|
sl@0
|
260 |
M3Guint bits = FLOAT_AS_UINT(x) + (1 << 23);
|
sl@0
|
261 |
return INT_AS_FLOAT(bits);
|
sl@0
|
262 |
}
|
sl@0
|
263 |
|
sl@0
|
264 |
/*!
|
sl@0
|
265 |
* \internal
|
sl@0
|
266 |
* \brief Computes the square of a floating point number
|
sl@0
|
267 |
*
|
sl@0
|
268 |
* \param x the input number
|
sl@0
|
269 |
* \return x * x
|
sl@0
|
270 |
*/
|
sl@0
|
271 |
static M3G_INLINE M3Gfloat m3gSquare(M3Gfloat x)
|
sl@0
|
272 |
{
|
sl@0
|
273 |
return m3gMul(x, x);
|
sl@0
|
274 |
}
|
sl@0
|
275 |
|
sl@0
|
276 |
/*!
|
sl@0
|
277 |
* \internal
|
sl@0
|
278 |
* \brief Negates a floating-point value
|
sl@0
|
279 |
*/
|
sl@0
|
280 |
static M3G_INLINE M3Gfloat m3gNegate(M3Gfloat x)
|
sl@0
|
281 |
{
|
sl@0
|
282 |
M3Guint ix = FLOAT_AS_UINT(x) ^ SIGN_MASK;
|
sl@0
|
283 |
return INT_AS_FLOAT(ix);
|
sl@0
|
284 |
}
|
sl@0
|
285 |
|
sl@0
|
286 |
#endif /*__M3G_MATH_H__*/
|