DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
mathlib.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// mathlib.c -- math primitives
21
22#include "quakedef.h"
23
24#include <math.h>
25
27float ixtable[4096];
28
29/*-----------------------------------------------------------------*/
30
32{
33{-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
34{-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
35{-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
36{0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
37{0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
38{0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
39{0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
40{0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
41{-0.809017f, 0.309017f, 0.500000f}, {-0.587785f, 0.425325f, 0.688191f},
42{-0.850651f, 0.525731f, 0.000000f}, {-0.864188f, 0.442863f, 0.238856f},
43{-0.716567f, 0.681718f, 0.147621f}, {-0.688191f, 0.587785f, 0.425325f},
44{-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
45{-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
46{-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
47{0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
48{0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
49{0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
50{-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
51{0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
52{0.238856f, 0.864188f, -0.442863f}, {0.262866f, 0.951056f, -0.162460f},
53{0.500000f, 0.809017f, -0.309017f}, {0.850651f, 0.525731f, 0.000000f},
54{0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
55{0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
56{0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
57{0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
58{0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
59{1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
60{0.850651f, -0.525731f, 0.000000f}, {0.955423f, -0.295242f, 0.000000f},
61{0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
62{0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
63{0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
64{0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
65{0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
66{0.681718f, -0.147621f, -0.716567f}, {0.850651f, 0.000000f, -0.525731f},
67{0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
68{0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
69{0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
70{0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
71{0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
72{-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
73{-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
74{-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
75{0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
76{0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
77{-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
78{0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
79{0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
80{0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
81{0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
82{0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
83{0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
84{0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
85{0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
86{0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
87{0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
88{0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
89{0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
90{-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
91{-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
92{-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
93{-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
94{-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
95{-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
96{-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
97{-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
98{-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
99{-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
100{0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
101{0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
102{0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
103{0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
104{-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
105{-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
106{-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
107{-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
108{-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
109{-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
110{-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
111{-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
112{-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
113{-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f},
114};
115
116#if 0
117unsigned char NormalToByte(const vec3_t n)
118{
119 int i, best;
120 float bestdistance, distance;
121
122 best = 0;
123 bestdistance = DotProduct (n, m_bytenormals[0]);
124 for (i = 1;i < NUMVERTEXNORMALS;i++)
125 {
126 distance = DotProduct (n, m_bytenormals[i]);
127 if (distance > bestdistance)
128 {
129 bestdistance = distance;
130 best = i;
131 }
132 }
133 return best;
134}
135
136// note: uses byte partly to force unsigned for the validity check
137void ByteToNormal(unsigned char num, vec3_t n)
138{
139 if (num < NUMVERTEXNORMALS)
141 else
142 VectorClear(n); // FIXME: complain?
143}
144
145// assumes "src" is normalized
146void PerpendicularVector( vec3_t dst, const vec3_t src )
147{
148 // LadyHavoc: optimized to death and beyond
149 int pos;
150 float minelem;
151
152 if (src[0])
153 {
154 dst[0] = 0;
155 if (src[1])
156 {
157 dst[1] = 0;
158 if (src[2])
159 {
160 dst[2] = 0;
161 pos = 0;
162 minelem = fabs(src[0]);
163 if (fabs(src[1]) < minelem)
164 {
165 pos = 1;
166 minelem = fabs(src[1]);
167 }
168 if (fabs(src[2]) < minelem)
169 pos = 2;
170
171 dst[pos] = 1;
172 dst[0] -= src[pos] * src[0];
173 dst[1] -= src[pos] * src[1];
174 dst[2] -= src[pos] * src[2];
175
176 // normalize the result
177 VectorNormalize(dst);
178 }
179 else
180 dst[2] = 1;
181 }
182 else
183 {
184 dst[1] = 1;
185 dst[2] = 0;
186 }
187 }
188 else
189 {
190 dst[0] = 1;
191 dst[1] = 0;
192 dst[2] = 0;
193 }
194}
195#endif
196
197
198// LadyHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
200{
201 // NOTE: this is consistent to AngleVectors applied to AnglesFromVectors
202 if (forward[0] == 0 && forward[1] == 0)
203 {
204 if(forward[2] > 0)
205 {
206 VectorSet(right, 0, -1, 0);
207 VectorSet(up, -1, 0, 0);
208 }
209 else
210 {
211 VectorSet(right, 0, -1, 0);
212 VectorSet(up, 1, 0, 0);
213 }
214 }
215 else
216 {
217 right[0] = forward[1];
218 right[1] = -forward[0];
219 right[2] = 0;
221
222 up[0] = (-forward[2]*forward[0]);
223 up[1] = (-forward[2]*forward[1]);
224 up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
226 }
227}
228
229void VectorVectorsDouble(const double *forward, double *right, double *up)
230{
231 if (forward[0] == 0 && forward[1] == 0)
232 {
233 if(forward[2] > 0)
234 {
235 VectorSet(right, 0, -1, 0);
236 VectorSet(up, -1, 0, 0);
237 }
238 else
239 {
240 VectorSet(right, 0, -1, 0);
241 VectorSet(up, 1, 0, 0);
242 }
243 }
244 else
245 {
246 right[0] = forward[1];
247 right[1] = -forward[0];
248 right[2] = 0;
250
251 up[0] = (-forward[2]*forward[0]);
252 up[1] = (-forward[2]*forward[1]);
253 up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
255 }
256}
257
258void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
259{
260 float t0, t1;
261 float angle, c, s;
262 vec3_t vr, vu, vf;
263
264 angle = DEG2RAD(degrees);
265 c = cos(angle);
266 s = sin(angle);
267 VectorCopy(dir, vf);
268 VectorVectors(vf, vr, vu);
269
270 t0 = vr[0] * c + vu[0] * -s;
271 t1 = vr[0] * s + vu[0] * c;
272 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
273 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
274 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
275
276 t0 = vr[1] * c + vu[1] * -s;
277 t1 = vr[1] * s + vu[1] * c;
278 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
279 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
280 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
281
282 t0 = vr[2] * c + vu[2] * -s;
283 t1 = vr[2] * s + vu[2] * c;
284 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
285 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
286 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
287}
288
289/*-----------------------------------------------------------------*/
290
291// returns the smallest integer greater than or equal to "value", or 0 if "value" is too big
292unsigned int CeilPowerOf2(unsigned int value)
293{
294 unsigned int ceilvalue;
295
296 if (value > (1U << (sizeof(int) * 8 - 1)))
297 return 0;
298
299 ceilvalue = 1;
300 while (ceilvalue < value)
301 ceilvalue <<= 1;
302
303 return ceilvalue;
304}
305
306
307/*-----------------------------------------------------------------*/
308
309
311{
312 // for optimized plane comparisons
313 if (p->normal[0] == 1)
314 p->type = 0;
315 else if (p->normal[1] == 1)
316 p->type = 1;
317 else if (p->normal[2] == 1)
318 p->type = 2;
319 else
320 p->type = 3;
321 // for BoxOnPlaneSide
322 p->signbits = 0;
323 if (p->normal[0] < 0) // 1
324 p->signbits |= 1;
325 if (p->normal[1] < 0) // 2
326 p->signbits |= 2;
327 if (p->normal[2] < 0) // 4
328 p->signbits |= 4;
329}
330
331int BoxOnPlaneSide(const vec3_t emins, const vec3_t emaxs, const mplane_t *p)
332{
333 if (p->type < 3)
334 return ((emaxs[p->type] >= p->dist) | ((emins[p->type] < p->dist) << 1));
335 switch(p->signbits)
336 {
337 default:
338 case 0: return (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) < p->dist) << 1));
339 case 1: return (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) < p->dist) << 1));
340 case 2: return (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) < p->dist) << 1));
341 case 3: return (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) < p->dist) << 1));
342 case 4: return (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
343 case 5: return (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
344 case 6: return (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
345 case 7: return (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
346 }
347}
348
349#if 0
350int BoxOnPlaneSide_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, const vec_t dist)
351{
352 switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
353 {
354 default:
355 case 0: return (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2]) < dist) << 1));
356 case 1: return (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2]) < dist) << 1));
357 case 2: return (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) < dist) << 1));
358 case 3: return (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) < dist) << 1));
359 case 4: return (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) < dist) << 1));
360 case 5: return (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) < dist) << 1));
361 case 6: return (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) < dist) << 1));
362 case 7: return (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) < dist) << 1));
363 }
364}
365#endif
366
367void BoxPlaneCorners(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec3_t outnear, vec3_t outfar)
368{
369 if (p->type < 3)
370 {
371 outnear[0] = outnear[1] = outnear[2] = outfar[0] = outfar[1] = outfar[2] = 0;
372 outnear[p->type] = emins[p->type];
373 outfar[p->type] = emaxs[p->type];
374 return;
375 }
376 switch(p->signbits)
377 {
378 default:
379 case 0: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
380 case 1: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
381 case 2: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
382 case 3: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
383 case 4: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
384 case 5: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
385 case 6: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
386 case 7: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
387 }
388}
389
390void BoxPlaneCorners_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec3_t outnear, vec3_t outfar)
391{
392 switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
393 {
394 default:
395 case 0: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
396 case 1: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
397 case 2: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
398 case 3: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
399 case 4: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
400 case 5: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
401 case 6: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
402 case 7: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
403 }
404}
405
406void BoxPlaneCornerDistances(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec_t *outneardist, vec_t *outfardist)
407{
408 if (p->type < 3)
409 {
410 *outneardist = emins[p->type] - p->dist;
411 *outfardist = emaxs[p->type] - p->dist;
412 return;
413 }
414 switch(p->signbits)
415 {
416 default:
417 case 0: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;break;
418 case 1: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;break;
419 case 2: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;break;
420 case 3: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;break;
421 case 4: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;break;
422 case 5: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;break;
423 case 6: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;break;
424 case 7: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;break;
425 }
426}
427
428void BoxPlaneCornerDistances_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec_t *outneardist, vec_t *outfardist)
429{
430 switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
431 {
432 default:
433 case 0: *outneardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2];break;
434 case 1: *outneardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2];break;
435 case 2: *outneardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2];break;
436 case 3: *outneardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2];break;
437 case 4: *outneardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2];*outfardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2];break;
438 case 5: *outneardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2];break;
439 case 6: *outneardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2];*outfardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];break;
440 case 7: *outneardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];break;
441 }
442}
443
445{
446 double angle, sr, sp, sy, cr, cp, cy;
447
448 angle = angles[YAW] * (M_PI*2 / 360);
449 sy = sin(angle);
450 cy = cos(angle);
451 angle = angles[PITCH] * (M_PI*2 / 360);
452 sp = sin(angle);
453 cp = cos(angle);
454 if (forward)
455 {
456 forward[0] = cp*cy;
457 forward[1] = cp*sy;
458 forward[2] = -sp;
459 }
460 if (right || up)
461 {
462 if (angles[ROLL])
463 {
464 angle = angles[ROLL] * (M_PI*2 / 360);
465 sr = sin(angle);
466 cr = cos(angle);
467 if (right)
468 {
469 right[0] = -1*(sr*sp*cy+cr*-sy);
470 right[1] = -1*(sr*sp*sy+cr*cy);
471 right[2] = -1*(sr*cp);
472 }
473 if (up)
474 {
475 up[0] = (cr*sp*cy+-sr*-sy);
476 up[1] = (cr*sp*sy+-sr*cy);
477 up[2] = cr*cp;
478 }
479 }
480 else
481 {
482 if (right)
483 {
484 right[0] = sy;
485 right[1] = -cy;
486 right[2] = 0;
487 }
488 if (up)
489 {
490 up[0] = (sp*cy);
491 up[1] = (sp*sy);
492 up[2] = cp;
493 }
494 }
495 }
496}
497
499{
500 double angle, sr, sp, sy, cr, cp, cy;
501
502 angle = angles[YAW] * (M_PI*2 / 360);
503 sy = sin(angle);
504 cy = cos(angle);
505 angle = angles[PITCH] * (M_PI*2 / 360);
506 sp = sin(angle);
507 cp = cos(angle);
508 if (forward)
509 {
510 forward[0] = cp*cy;
511 forward[1] = cp*sy;
512 forward[2] = -sp;
513 }
514 if (left || up)
515 {
516 if (angles[ROLL])
517 {
518 angle = angles[ROLL] * (M_PI*2 / 360);
519 sr = sin(angle);
520 cr = cos(angle);
521 if (left)
522 {
523 left[0] = sr*sp*cy+cr*-sy;
524 left[1] = sr*sp*sy+cr*cy;
525 left[2] = sr*cp;
526 }
527 if (up)
528 {
529 up[0] = cr*sp*cy+-sr*-sy;
530 up[1] = cr*sp*sy+-sr*cy;
531 up[2] = cr*cp;
532 }
533 }
534 else
535 {
536 if (left)
537 {
538 left[0] = -sy;
539 left[1] = cy;
540 left[2] = 0;
541 }
542 if (up)
543 {
544 up[0] = sp*cy;
545 up[1] = sp*sy;
546 up[2] = cp;
547 }
548 }
549 }
550}
551
552void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up, double maxShearAngle)
553{
554 double angle, sr, sy, cr, cy;
555 double sxx, sxz, szx, szz;
556 double cosMaxShearAngle = cos(maxShearAngle * (M_PI*2 / 360));
557 double tanMaxShearAngle = tan(maxShearAngle * (M_PI*2 / 360));
558
559 angle = angles[YAW] * (M_PI*2 / 360);
560 sy = sin(angle);
561 cy = cos(angle);
562 angle = angles[PITCH] * (M_PI*2 / 360);
563
564 // We will calculate a shear matrix pitch = [[sxx sxz][szx szz]].
565
566 if (fabs(cos(angle)) > cosMaxShearAngle)
567 {
568 // Pure shear. Keep the original sign of the coefficients.
569 sxx = 1;
570 sxz = 0;
571 szx = -tan(angle);
572 szz = 1;
573 // Covering angle per screen coordinate:
574 // d/dt arctan((sxz + t*szz) / (sxx + t*szx)) @ t=0
575 // d_angle = det(S) / (sxx*sxx + szx*szx)
576 // = 1 / (1 + tan^2 angle)
577 // = cos^2 angle.
578 }
579 else
580 {
581 // A mix of shear and rotation. Implementation-wise, we're
582 // looking at a capsule, and making the screen surface
583 // tangential to it... and if we get here, we're looking at the
584 // two half-spheres of the capsule (and the cylinder part is
585 // handled above).
586 double x, y, h, t, d, f;
587 h = tanMaxShearAngle;
588 x = cos(angle);
589 y = sin(angle);
590 t = h * fabs(y) + sqrt(1 - (h * x) * (h * x));
591 sxx = x * t;
592 sxz = y * t - h * (y > 0 ? 1.0 : -1.0);
593 szx = -y * t;
594 szz = x * t;
595 // BUT: keep the amount of a sphere we see in pitch direction
596 // invariant.
597 // Covering angle per screen coordinate:
598 // d_angle = det(S) / (sxx*sxx + szx*szx)
599 d = (sxx * szz - sxz * szx) / (sxx * sxx + szx * szx);
600 f = cosMaxShearAngle * cosMaxShearAngle / d;
601 sxz *= f;
602 szz *= f;
603 }
604
605 if (forward)
606 {
607 forward[0] = sxx*cy;
608 forward[1] = sxx*sy;
609 forward[2] = szx;
610 }
611 if (left || up)
612 {
613 if (angles[ROLL])
614 {
615 angle = angles[ROLL] * (M_PI*2 / 360);
616 sr = sin(angle);
617 cr = cos(angle);
618 if (left)
619 {
620 left[0] = sr*sxz*cy+cr*-sy;
621 left[1] = sr*sxz*sy+cr*cy;
622 left[2] = sr*szz;
623 }
624 if (up)
625 {
626 up[0] = cr*sxz*cy+-sr*-sy;
627 up[1] = cr*sxz*sy+-sr*cy;
628 up[2] = cr*szz;
629 }
630 }
631 else
632 {
633 if (left)
634 {
635 left[0] = -sy;
636 left[1] = cy;
637 left[2] = 0;
638 }
639 if (up)
640 {
641 up[0] = sxz*cy;
642 up[1] = sxz*sy;
643 up[2] = szz;
644 }
645 }
646 }
647}
648
649// LadyHavoc: calculates pitch/yaw/roll angles from forward and up vectors
651{
652 if (forward[0] == 0 && forward[1] == 0)
653 {
654 if(forward[2] > 0)
655 {
656 angles[PITCH] = -M_PI * 0.5;
657 angles[YAW] = up ? atan2(-up[1], -up[0]) : 0;
658 }
659 else
660 {
661 angles[PITCH] = M_PI * 0.5;
662 angles[YAW] = up ? atan2(up[1], up[0]) : 0;
663 }
664 angles[ROLL] = 0;
665 }
666 else
667 {
668 angles[YAW] = atan2(forward[1], forward[0]);
669 angles[PITCH] = -atan2(forward[2], sqrt(forward[0]*forward[0] + forward[1]*forward[1]));
670 // note: we know that angles[PITCH] is in ]-pi/2..pi/2[ due to atan2(anything, positive)
671 if (up)
672 {
673 vec_t cp = cos(angles[PITCH]), sp = sin(angles[PITCH]);
674 // note: we know cp > 0, due to the range angles[pitch] is in
675 vec_t cy = cos(angles[YAW]), sy = sin(angles[YAW]);
676 vec3_t tleft, tup;
677 tleft[0] = -sy;
678 tleft[1] = cy;
679 tleft[2] = 0;
680 tup[0] = sp*cy;
681 tup[1] = sp*sy;
682 tup[2] = cp;
683 angles[ROLL] = -atan2(DotProduct(up, tleft), DotProduct(up, tup));
684 // for up == '0 0 1', this is
685 // angles[ROLL] = -atan2(0, cp);
686 // which is 0
687 }
688 else
689 angles[ROLL] = 0;
690
691 // so no up vector is equivalent to '1 0 0'!
692 }
693
694 // now convert radians to degrees, and make all values positive
695 VectorScale(angles, 180.0 / M_PI, angles);
696 if (flippitch)
697 angles[PITCH] *= -1;
698 if (angles[PITCH] < 0) angles[PITCH] += 360;
699 if (angles[YAW] < 0) angles[YAW] += 360;
700 if (angles[ROLL] < 0) angles[ROLL] += 360;
701
702#if 0
703{
704 // debugging code
705 vec3_t tforward, tleft, tup, nforward, nup;
706 VectorCopy(forward, nforward);
707 VectorNormalize(nforward);
708 if (up)
709 {
710 VectorCopy(up, nup);
711 VectorNormalize(nup);
712 AngleVectors(angles, tforward, tleft, tup);
713 if (VectorDistance(tforward, nforward) > 0.01 || VectorDistance(tup, nup) > 0.01)
714 {
715 Con_Printf("vectoangles('%f %f %f', '%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], nup[0], nup[1], nup[2], angles[0], angles[1], angles[2]);
716 Con_Printf("^3But that is '%f %f %f', '%f %f %f'\n", tforward[0], tforward[1], tforward[2], tup[0], tup[1], tup[2]);
717 }
718 }
719 else
720 {
721 AngleVectors(angles, tforward, tleft, tup);
722 if (VectorDistance(tforward, nforward) > 0.01)
723 {
724 Con_Printf("vectoangles('%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], angles[0], angles[1], angles[2]);
725 Con_Printf("^3But that is '%f %f %f'\n", tforward[0], tforward[1], tforward[2]);
726 }
727 }
728}
729#endif
730}
731
732#if 0
733void AngleMatrix (const vec3_t angles, const vec3_t translate, vec_t matrix[][4])
734{
735 double angle, sr, sp, sy, cr, cp, cy;
736
737 angle = angles[YAW] * (M_PI*2 / 360);
738 sy = sin(angle);
739 cy = cos(angle);
740 angle = angles[PITCH] * (M_PI*2 / 360);
741 sp = sin(angle);
742 cp = cos(angle);
743 angle = angles[ROLL] * (M_PI*2 / 360);
744 sr = sin(angle);
745 cr = cos(angle);
746 matrix[0][0] = cp*cy;
747 matrix[0][1] = sr*sp*cy+cr*-sy;
748 matrix[0][2] = cr*sp*cy+-sr*-sy;
749 matrix[0][3] = translate[0];
750 matrix[1][0] = cp*sy;
751 matrix[1][1] = sr*sp*sy+cr*cy;
752 matrix[1][2] = cr*sp*sy+-sr*cy;
753 matrix[1][3] = translate[1];
754 matrix[2][0] = -sp;
755 matrix[2][1] = sr*cp;
756 matrix[2][2] = cr*cp;
757 matrix[2][3] = translate[2];
758}
759#endif
760
761
762// LadyHavoc: renamed this to Length, and made the normal one a #define
764{
765 float length;
766
768
769 if (length)
770 VectorScale(v, 1 / length, v);
771
772 return length;
773}
774
775
776/*
777================
778R_ConcatRotations
779================
780*/
781void R_ConcatRotations (const float in1[3*3], const float in2[3*3], float out[3*3])
782{
783 out[0*3+0] = in1[0*3+0] * in2[0*3+0] + in1[0*3+1] * in2[1*3+0] + in1[0*3+2] * in2[2*3+0];
784 out[0*3+1] = in1[0*3+0] * in2[0*3+1] + in1[0*3+1] * in2[1*3+1] + in1[0*3+2] * in2[2*3+1];
785 out[0*3+2] = in1[0*3+0] * in2[0*3+2] + in1[0*3+1] * in2[1*3+2] + in1[0*3+2] * in2[2*3+2];
786 out[1*3+0] = in1[1*3+0] * in2[0*3+0] + in1[1*3+1] * in2[1*3+0] + in1[1*3+2] * in2[2*3+0];
787 out[1*3+1] = in1[1*3+0] * in2[0*3+1] + in1[1*3+1] * in2[1*3+1] + in1[1*3+2] * in2[2*3+1];
788 out[1*3+2] = in1[1*3+0] * in2[0*3+2] + in1[1*3+1] * in2[1*3+2] + in1[1*3+2] * in2[2*3+2];
789 out[2*3+0] = in1[2*3+0] * in2[0*3+0] + in1[2*3+1] * in2[1*3+0] + in1[2*3+2] * in2[2*3+0];
790 out[2*3+1] = in1[2*3+0] * in2[0*3+1] + in1[2*3+1] * in2[1*3+1] + in1[2*3+2] * in2[2*3+1];
791 out[2*3+2] = in1[2*3+0] * in2[0*3+2] + in1[2*3+1] * in2[1*3+2] + in1[2*3+2] * in2[2*3+2];
792}
793
794
795/*
796================
797R_ConcatTransforms
798================
799*/
800void R_ConcatTransforms (const float in1[3*4], const float in2[3*4], float out[3*4])
801{
802 out[0*4+0] = in1[0*4+0] * in2[0*4+0] + in1[0*4+1] * in2[1*4+0] + in1[0*4+2] * in2[2*4+0];
803 out[0*4+1] = in1[0*4+0] * in2[0*4+1] + in1[0*4+1] * in2[1*4+1] + in1[0*4+2] * in2[2*4+1];
804 out[0*4+2] = in1[0*4+0] * in2[0*4+2] + in1[0*4+1] * in2[1*4+2] + in1[0*4+2] * in2[2*4+2];
805 out[0*4+3] = in1[0*4+0] * in2[0*4+3] + in1[0*4+1] * in2[1*4+3] + in1[0*4+2] * in2[2*4+3] + in1[0*4+3];
806 out[1*4+0] = in1[1*4+0] * in2[0*4+0] + in1[1*4+1] * in2[1*4+0] + in1[1*4+2] * in2[2*4+0];
807 out[1*4+1] = in1[1*4+0] * in2[0*4+1] + in1[1*4+1] * in2[1*4+1] + in1[1*4+2] * in2[2*4+1];
808 out[1*4+2] = in1[1*4+0] * in2[0*4+2] + in1[1*4+1] * in2[1*4+2] + in1[1*4+2] * in2[2*4+2];
809 out[1*4+3] = in1[1*4+0] * in2[0*4+3] + in1[1*4+1] * in2[1*4+3] + in1[1*4+2] * in2[2*4+3] + in1[1*4+3];
810 out[2*4+0] = in1[2*4+0] * in2[0*4+0] + in1[2*4+1] * in2[1*4+0] + in1[2*4+2] * in2[2*4+0];
811 out[2*4+1] = in1[2*4+0] * in2[0*4+1] + in1[2*4+1] * in2[1*4+1] + in1[2*4+2] * in2[2*4+1];
812 out[2*4+2] = in1[2*4+0] * in2[0*4+2] + in1[2*4+1] * in2[1*4+2] + in1[2*4+2] * in2[2*4+2];
813 out[2*4+3] = in1[2*4+0] * in2[0*4+3] + in1[2*4+1] * in2[1*4+3] + in1[2*4+2] * in2[2*4+3] + in1[2*4+3];
814}
815
817{
818 vec3_t m1, m2;
821 return sqrt(max(m1[0], m2[0]) + max(m1[1], m2[1]) + max(m1[2], m2[2]));
822}
823
825{
826 vec3_t m1, m2;
827 VectorSubtract(mins, origin, m1);VectorMultiply(m1, m1, m1);
828 VectorSubtract(maxs, origin, m2);VectorMultiply(m2, m2, m2);
829 return sqrt(max(m1[0], m2[0]) + max(m1[1], m2[1]) + max(m1[2], m2[2]));
830}
831
832static void Math_RandomSeed_UnitTests(void);
833void Mathlib_Init(void)
834{
835 int a;
836
837 // LadyHavoc: setup 1.0f / N table for quick recipricols of integers
838 ixtable[0] = 0;
839 for (a = 1;a < 4096;a++)
840 ixtable[a] = 1.0f / a;
841
843}
844
845#include "matrixlib.h"
846
848{
849 Con_Printf("%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n"
850 , in->m[0][0], in->m[0][1], in->m[0][2], in->m[0][3]
851 , in->m[1][0], in->m[1][1], in->m[1][2], in->m[1][3]
852 , in->m[2][0], in->m[2][1], in->m[2][2], in->m[2][3]
853 , in->m[3][0], in->m[3][1], in->m[3][2], in->m[3][3]);
854}
855
856int Math_atov(const char *s, prvm_vec3_t out)
857{
858 int i;
859 VectorClear(out);
860 if (*s == '\'')
861 s++;
862 for (i = 0;i < 3;i++)
863 {
864 while (*s == ' ' || *s == '\t')
865 s++;
866 out[i] = atof (s);
867 if (out[i] == 0 && *s != '-' && *s != '+' && (*s < '0' || *s > '9'))
868 break; // not a number
869 while (*s && *s != ' ' && *s !='\t' && *s != '\'')
870 s++;
871 if (*s == '\'')
872 break;
873 }
874 return i;
875}
876
877void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f)
878{
879 int i;
880 VectorCopy(point3f, mins);
881 VectorCopy(point3f, maxs);
882 for (i = 1, point3f += 3;i < numpoints;i++, point3f += 3)
883 {
884 mins[0] = min(mins[0], point3f[0]);maxs[0] = max(maxs[0], point3f[0]);
885 mins[1] = min(mins[1], point3f[1]);maxs[1] = max(maxs[1], point3f[1]);
886 mins[2] = min(mins[2], point3f[2]);maxs[2] = max(maxs[2], point3f[2]);
887 }
888}
889
890// LadyHavoc: this has to be done right or you get severe precision breakdown
891int LoopingFrameNumberFromDouble(double t, int loopframes)
892{
893 if (loopframes)
894 return (int)(t - floor(t/loopframes)*loopframes);
895 else
896 return (int)t;
897}
898
899static unsigned int mul_Lecuyer[4] = { 0x12e15e35, 0xb500f16e, 0x2e714eb2, 0xb37916a5 };
900
901static void mul128(const unsigned int a[], const unsigned int b[], unsigned int dest[4])
902{
903#if 0 //defined(__GNUC__) && defined(__x86_64__)
904 unsigned __int128 ia = ((__int128)a[0] << 96) | ((__int128)a[1] << 64) | ((__int128)a[2] << 32) | (a[3]);
905 unsigned __int128 ib = ((__int128)b[0] << 96) | ((__int128)b[1] << 64) | ((__int128)b[2] << 32) | (b[3]);
906 unsigned __int128 id = ia * ib;
907 dest[0] = (id >> 96) & 0xffffffff;
908 dest[1] = (id >> 64) & 0xffffffff;
909 dest[2] = (id >> 32) & 0xffffffff;
910 dest[3] = (id) & 0xffffffff;
911#else
912 unsigned long long t[4];
913
914 // this multiply chain is relatively straightforward - a[] is repeatedly
915 // added with shifts based on b[] and the results stored into uint64,
916 // but due to C limitations (no access to carry flag) we have to resolve
917 // carries in a really lame way which wastes a fair number of ops
918 // (repeatedly iterating MSB to LSB, rather than LSB to MSB with carry),
919 // an alternative would be to use 16bit multiplies and resolve carries
920 // only at the end, but that would be twice as many multiplies...
921 //
922 // note: >> 32 is a function call in win32 MSVS2015 debug builds.
923 t[0] = (unsigned long long)a[0] * b[3];
924 t[1] = (unsigned long long)a[1] * b[3];
925 t[2] = (unsigned long long)a[2] * b[3];
926 t[3] = (unsigned long long)a[3] * b[3];
927 t[0] += t[1] >> 32;
928 t[1] &= 0xffffffff;
929 t[1] += t[2] >> 32;
930 t[2] &= 0xffffffff;
931 t[2] += t[3] >> 32;
932
933 t[0] += t[1] >> 32;
934 t[1] &= 0xffffffff;
935 t[1] += t[2] >> 32;
936 t[2] &= 0xffffffff;
937
938 t[0] += t[1] >> 32;
939 t[1] &= 0xffffffff;
940
941 t[0] += (unsigned long long)a[1] * b[2];
942 t[1] += (unsigned long long)a[2] * b[2];
943 t[2] += (unsigned long long)a[3] * b[2];
944 t[0] += t[1] >> 32;
945 t[1] &= 0xffffffff;
946 t[1] += t[2] >> 32;
947
948 t[0] += t[1] >> 32;
949 t[1] &= 0xffffffff;
950
951 t[0] += (unsigned long long)a[2] * b[1];
952 t[1] += (unsigned long long)a[3] * b[1];
953 t[0] += t[1] >> 32;
954
955 t[0] += (unsigned long long)a[3] * b[0];
956
957 dest[0] = t[0] & 0xffffffff;
958 dest[1] = t[1] & 0xffffffff;
959 dest[2] = t[2] & 0xffffffff;
960 dest[3] = t[3] & 0xffffffff;
961#endif
962}
963
964static void testmul128(unsigned int a0, unsigned int a1, unsigned int a2, unsigned int a3, unsigned int b0, unsigned int b1, unsigned int b2, unsigned int b3, unsigned int x0, unsigned int x1, unsigned int x2, unsigned int x3)
965{
966 unsigned int a[4];
967 unsigned int b[4];
968 unsigned int expected[4];
969 unsigned int result[4];
970 a[0] = a0;
971 a[1] = a1;
972 a[2] = a2;
973 a[3] = a3;
974 b[0] = b0;
975 b[1] = b1;
976 b[2] = b2;
977 b[3] = b3;
978 expected[0] = x0;
979 expected[1] = x1;
980 expected[2] = x2;
981 expected[3] = x3;
982 mul128(a, b, result);
983 if (result[0] != expected[0]
984 || result[1] != expected[1]
985 || result[2] != expected[2]
986 || result[3] != expected[3])
987 Con_Printf("testmul128(\na = %08x %08x %08x %08x,\nb = %08x %08x %08x %08x,\nx = %08x %08x %08x %08x) instead computed\nc = %08x %08x %08x %08x\n", a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3], expected[0], expected[1], expected[2], expected[3], result[0], result[1], result[2], result[3]);
988}
989
991{
993 0x00000000, 0x00000000, 0x00000000, 0x00000001,
994 0x00000000, 0x00000000, 0x00000000, 0x00000001,
995 0x00000000, 0x00000000, 0x00000000, 0x00000001);
997 0x00000000, 0x00000000, 0x00000000, 0x00000001,
998 0x00000000, 0x00000000, 0x00000001, 0x00000000,
999 0x00000000, 0x00000000, 0x00000001, 0x00000000);
1000 testmul128(
1001 0x00000000, 0x00000000, 0x00000001, 0x00000000,
1002 0x00000000, 0x00000000, 0x00000000, 0x00000001,
1003 0x00000000, 0x00000000, 0x00000001, 0x00000000);
1004 testmul128(
1005 0x00000000, 0x00000000, 0x00000000, 0x00000001,
1006 0x00000001, 0x00000001, 0x00000001, 0x00000001,
1007 0x00000001, 0x00000001, 0x00000001, 0x00000001);
1008 testmul128(
1009 0x00000000, 0x00000000, 0x00000000, 0x00000002,
1010 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
1011 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe);
1012 testmul128(
1013 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
1014 0x00000000, 0x00000000, 0x00000000, 0x00000002,
1015 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe);
1016 testmul128(
1017 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
1018 0x00000000, 0x00000000, 0x00000002, 0x00000000,
1019 0x00000001, 0xffffffff, 0xfffffffe, 0x00000000);
1020 testmul128(
1021 0x00000000, 0x00000000, 0x00000002, 0x00000000,
1022 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
1023 0x00000001, 0xffffffff, 0xfffffffe, 0x00000000);
1024}
1025
1027{
1028 r->s[0] = 1;
1029 r->s[1] = 0;
1030 r->s[2] = 0;
1031 r->s[3] = 0;
1032}
1033
1034void Math_RandomSeed_FromInts(randomseed_t *r, unsigned int s0, unsigned int s1, unsigned int s2, unsigned int s3)
1035{
1036 r->s[0] = s0;
1037 r->s[1] = s1;
1038 r->s[2] = s2;
1039 r->s[3] = s3 | 1; // the Lehmer RNG requires that the seed be odd
1040}
1041
1042unsigned long long Math_rand64(randomseed_t *r)
1043{
1044 unsigned int o[4];
1045 mul128(r->s, mul_Lecuyer, o);
1046 r->s[0] = o[0];
1047 r->s[1] = o[1];
1048 r->s[2] = o[2];
1049 r->s[3] = o[3];
1050 return ((unsigned long long)o[3] << 32) + o[2];
1051}
1052
1054{
1055 unsigned long long n = Math_rand64(r);
1056 return n * (0.25f / 0x80000000 / 0x80000000);
1057}
1058
1060{
1061 // do this with a signed number and double the result, so we make use of all parts of the cow
1062 long long n = (long long)Math_rand64(r);
1063 return n * (0.5f / 0x80000000 / 0x80000000);
1064}
1065
1066float Math_randomrangef(randomseed_t *r, float minf, float maxf)
1067{
1068 return Math_randomf(r) * (maxf - minf) + minf;
1069}
1070
1071int Math_randomrangei(randomseed_t *r, int mini, int maxi)
1072{
1073 unsigned long long n = Math_rand64(r);
1074 return (int)(((n >> 33) * (maxi - mini) + mini) >> 31);
1075}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
vector mins
vector maxs
vector angles
vector origin
#define n(x, y)
GLenum GLuint id
Definition glquake.h:657
GLsizei const GLfloat * value
Definition glquake.h:740
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
const GLdouble * v
Definition glquake.h:762
GLint GLenum GLint GLint y
Definition glquake.h:651
GLint GLenum GLint x
Definition glquake.h:651
static void testmul128(unsigned int a0, unsigned int a1, unsigned int a2, unsigned int a3, unsigned int b0, unsigned int b1, unsigned int b2, unsigned int b3, unsigned int x0, unsigned int x1, unsigned int x2, unsigned int x3)
Definition mathlib.c:964
void Mathlib_Init(void)
Definition mathlib.c:833
static unsigned int mul_Lecuyer[4]
Definition mathlib.c:899
float RadiusFromBounds(const vec3_t mins, const vec3_t maxs)
Definition mathlib.c:816
void VectorVectorsDouble(const double *forward, double *right, double *up)
Definition mathlib.c:229
float Math_crandomf(randomseed_t *r)
Definition mathlib.c:1059
void AngleVectorsDuke3DFLU(const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up, double maxShearAngle)
divVerent: improper matrix version of AngleVectors
Definition mathlib.c:552
void Math_RandomSeed_FromInts(randomseed_t *r, unsigned int s0, unsigned int s1, unsigned int s2, unsigned int s3)
Definition mathlib.c:1034
void BoxPlaneCornerDistances_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec_t *outneardist, vec_t *outfardist)
Definition mathlib.c:428
float RadiusFromBoundsAndOrigin(const vec3_t mins, const vec3_t maxs, const vec3_t origin)
Definition mathlib.c:824
vec3_t vec3_origin
Definition mathlib.c:26
int LoopingFrameNumberFromDouble(double t, int loopframes)
Definition mathlib.c:891
float Math_randomf(randomseed_t *r)
Definition mathlib.c:1053
float Math_randomrangef(randomseed_t *r, float minf, float maxf)
Definition mathlib.c:1066
int Math_atov(const char *s, prvm_vec3_t out)
Definition mathlib.c:856
void AnglesFromVectors(vec3_t angles, const vec3_t forward, const vec3_t up, qbool flippitch)
LadyHavoc: calculates pitch/yaw/roll angles from forward and up vectors.
Definition mathlib.c:650
void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f)
Definition mathlib.c:877
void AngleVectorsFLU(const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
LadyHavoc: proper matrix version of AngleVectors.
Definition mathlib.c:498
float m_bytenormals[NUMVERTEXNORMALS][3]
Definition mathlib.c:31
unsigned long long Math_rand64(randomseed_t *r)
Definition mathlib.c:1042
float ixtable[4096]
Definition mathlib.c:27
void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees)
Definition mathlib.c:258
unsigned int CeilPowerOf2(unsigned int value)
returns the smallest integer greater than or equal to "value", or 0 if "value" is too big
Definition mathlib.c:292
void R_ConcatTransforms(const float in1[3 *4], const float in2[3 *4], float out[3 *4])
Definition mathlib.c:800
static void Math_RandomSeed_UnitTests(void)
Definition mathlib.c:990
void BoxPlaneCornerDistances(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec_t *outneardist, vec_t *outfardist)
Definition mathlib.c:406
float VectorNormalizeLength(vec3_t v)
returns vector length
Definition mathlib.c:763
void Math_RandomSeed_Reset(randomseed_t *r)
Definition mathlib.c:1026
void BoxPlaneCorners(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec3_t outnear, vec3_t outfar)
Definition mathlib.c:367
int Math_randomrangei(randomseed_t *r, int mini, int maxi)
Definition mathlib.c:1071
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition mathlib.c:444
static void mul128(const unsigned int a[], const unsigned int b[], unsigned int dest[4])
Definition mathlib.c:901
void PlaneClassify(mplane_t *p)
Definition mathlib.c:310
void Matrix4x4_Print(const matrix4x4_t *in)
Definition mathlib.c:847
void BoxPlaneCorners_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec3_t outnear, vec3_t outfar)
Definition mathlib.c:390
void R_ConcatRotations(const float in1[3 *3], const float in2[3 *3], float out[3 *3])
Definition mathlib.c:781
int BoxOnPlaneSide(const vec3_t emins, const vec3_t emaxs, const mplane_t *p)
Definition mathlib.c:331
void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
LadyHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
Definition mathlib.c:199
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
#define VectorNormalize(v)
Definition mathlib.h:104
#define DEG2RAD(a)
Definition mathlib.h:65
#define VectorClear(a)
Definition mathlib.h:97
unsigned char NormalToByte(const vec3_t n)
void AngleMatrix(const vec3_t angles, const vec3_t translate, vec_t matrix[][4])
LadyHavoc: builds a [3][4] matrix.
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
int BoxOnPlaneSide_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, const vec_t dist)
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define NUMVERTEXNORMALS
Definition mathlib.h:225
#define VectorMultiply(a, b, out)
Definition mathlib.h:102
#define VectorDistance(a, b)
Definition mathlib.h:108
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorCopy(in, out)
Definition mathlib.h:101
void ByteToNormal(unsigned char num, vec3_t n)
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define M_PI
Definition mathlib.h:28
float cos(float f)
float sqrt(float f)
float sin(float f)
float fabs(float f)
float floor(float f)
prvm_eval_t * src
int i
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
prvm_vec_t prvm_vec3_t[3]
Definition qtypes.h:63
bool qbool
Definition qtypes.h:9
#define YAW
Definition qtypes.h:19
#define PITCH
Definition qtypes.h:16
#define ROLL
Definition qtypes.h:22
dp_FragColor r
vec2 dir
vec3 x3
float f
vec3 x2
vec3 normal
dp_FragColor b
vec3 x1
ret a
vec_t m[4][4]
Definition matrixlib.h:11
vec3_t normal
Definition model_brush.h:59
vec_t dist
Definition model_brush.h:60
int signbits
Definition model_brush.h:66
static vec3_t forward
Definition sv_user.c:305
static vec3_t right
Definition sv_user.c:305
static vec3_t up
Definition sv_user.c:305