1 /*
2 WORLD.H
3
4 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 and the "Aleph One" developers.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 This license is contained in the file "COPYING",
18 which is included with this source code; it is available online at
19 http://www.gnu.org/licenses/gpl.html
20
21 Wednesday, June 17, 1992 6:40:10 PM
22
23 Friday, June 26, 1992 10:47:47 AM
24 to maintain precision when squaring world coordinates, they must be in [0,32*WORLD_ONE).
25 Wednesday, August 18, 1993 2:59:47 PM
26 added 3d world points, world_distance is now a short (because we care).
27 Sunday, May 22, 1994 10:48:26 PM
28 added fixed_point3d. GUESS_HYPOTENUSE() is no longer completely broken.
29
30 Feb 15, 2000 (Loren Petrich):
31 Moved definition of "long" versions of vectors into here
32
33 Feb 17, 2000 (Loren Petrich):
34 Made the arctangent function long-distance friendly
35
36 Jul 1, 2000 (Loren Petrich):
37 Inlined the angle normalization; using tricky code for that
38 */
39
40 #ifndef _WORLD_H
41 #define _WORLD_H
42
43 #include "cstypes.h"
44
45 /* ---------- constants */
46
47 #define TRIG_SHIFT 10
48 #define TRIG_MAGNITUDE (1<<TRIG_SHIFT)
49
50 #define ANGULAR_BITS 9
51 #define NUMBER_OF_ANGLES ((short)(1<<ANGULAR_BITS))
52 #define FULL_CIRCLE NUMBER_OF_ANGLES
53 #define QUARTER_CIRCLE ((short)(NUMBER_OF_ANGLES/4))
54 #define HALF_CIRCLE ((short)(NUMBER_OF_ANGLES/2))
55 #define THREE_QUARTER_CIRCLE ((short)((NUMBER_OF_ANGLES*3)/4))
56 #define EIGHTH_CIRCLE ((short)(NUMBER_OF_ANGLES/8))
57 #define SIXTEENTH_CIRCLE ((short)(NUMBER_OF_ANGLES/16))
58
59 #define WORLD_FRACTIONAL_BITS 10
60 #define WORLD_ONE ((world_distance)(1<<WORLD_FRACTIONAL_BITS))
61 #define WORLD_ONE_HALF ((world_distance)(WORLD_ONE/2))
62 #define WORLD_ONE_FOURTH ((world_distance)(WORLD_ONE/4))
63 #define WORLD_THREE_FOURTHS ((world_distance)((WORLD_ONE*3)/4))
64
65 #define DEFAULT_RANDOM_SEED ((uint16)0xfded)
66
67 /* ---------- types */
68
69 typedef int16 angle;
70 typedef _fixed fixed_angle; // angle with _fixed precision
71 typedef int16 world_distance;
72
73 /* ---------- macros */
74
75 #define INTEGER_TO_WORLD(s) (((world_distance)(s))<<WORLD_FRACTIONAL_BITS)
76 #define WORLD_FRACTIONAL_PART(d) ((d)&((world_distance)(WORLD_ONE-1)))
77 #define WORLD_INTEGERAL_PART(d) ((d)>>WORLD_FRACTIONAL_BITS)
78
79 #define WORLD_TO_FIXED(w) (((_fixed)(w))<<(FIXED_FRACTIONAL_BITS-WORLD_FRACTIONAL_BITS))
80 #define FIXED_TO_WORLD(f) ((world_distance)((f)>>(FIXED_FRACTIONAL_BITS-WORLD_FRACTIONAL_BITS)))
81
82 #define FACING4(a) (NORMALIZE_ANGLE((a)-EIGHTH_CIRCLE)>>(ANGULAR_BITS-2))
83 #define FACING5(a) ((NORMALIZE_ANGLE((a)-FULL_CIRCLE/10))/((NUMBER_OF_ANGLES/5)+1))
84 #define FACING8(a) (NORMALIZE_ANGLE((a)-SIXTEENTH_CIRCLE)>>(ANGULAR_BITS-3))
85
86 /* arguments must be positive (!) or use guess_hypotenuse() */
87 #define GUESS_HYPOTENUSE(x, y) ((x)>(y) ? ((x)+((y)>>1)) : ((y)+((x)>>1)))
88
89 /* -360�<t<720� (!) or use normalize_angle() */
90 //#define NORMALIZE_ANGLE(t) ((t)<(angle)0?(t)+NUMBER_OF_ANGLES:((t)>=NUMBER_OF_ANGLES?(t)-NUMBER_OF_ANGLES:(t)))
91 #define NORMALIZE_ANGLE(t) ((t)&(angle)(NUMBER_OF_ANGLES-1))
92
93 /* ---------- point structures */
94
95 struct world_point2d
96 {
97 world_distance x, y;
98 };
99 typedef struct world_point2d world_point2d;
100
101 struct world_point3d
102 {
103 world_distance x, y, z;
104 };
105 typedef struct world_point3d world_point3d;
106
107 struct fixed_point3d
108 {
109 _fixed x, y, z;
110 };
111 typedef struct fixed_point3d fixed_point3d;
112
113 /* ---------- vector structures */
114
115 struct world_vector2d
116 {
117 world_distance i, j;
118 };
119 typedef struct world_vector2d world_vector2d;
120
121 struct world_vector3d
122 {
123 world_distance i, j, k;
124 };
125 typedef struct world_vector3d world_vector3d;
126
127 struct fixed_vector3d
128 {
129 _fixed i, j, k;
130 };
131 typedef struct fixed_vector3d fixed_vector3d;
132
133 // LP addition: long-integer intermediate values for better long-distance calculation
134
135 struct long_point2d
136 {
137 int32 x, y;
138 };
139 typedef struct long_point2d long_point2d;
140
141 struct long_point3d
142 {
143 int32 x, y, z;
144 };
145 typedef struct long_point3d long_point3d;
146
147 struct long_vector2d
148 {
149 int32 i, j;
150 };
151 typedef struct long_vector2d long_vector2d;
152
153 struct long_vector3d
154 {
155 int32 i, j, k;
156 };
157 typedef struct long_vector3d long_vector3d;
158
159 /* ---------- angle structures */
160
161 // A relative or (possibly non-normalized) absolute direction
162 struct fixed_yaw_pitch { fixed_angle yaw, pitch; };
163
164 /* ---------- locations */
165
166 struct world_location3d
167 {
168 world_point3d point;
169 short polygon_index;
170
171 angle yaw, pitch;
172
173 world_vector3d velocity;
174 };
175 typedef struct world_location3d world_location3d;
176
177 /* ---------- globals */
178
179 extern short *cosine_table, *sine_table;
180 /* tangent table is for internal use only (during arctangent calls) */
181
182 /* ---------- prototypes: WORLD.C */
183
184 void build_trig_tables(void);
185
186 // LP change: inlined this for speed, and used the NORMALIZE_ANGLE macro;
187 // looks as if the code had been worked on by more than one programmer.
normalize_angle(angle theta)188 static inline angle normalize_angle(angle theta)
189 {
190 return NORMALIZE_ANGLE(theta);
191 }
192
193 world_point2d *rotate_point2d(world_point2d *point, world_point2d *origin, angle theta);
194 world_point3d *rotate_point3d(world_point3d *point, world_point3d *origin, angle theta, angle phi);
195
196 world_point2d *translate_point2d(world_point2d *point, world_distance distance, angle theta);
197 world_point3d *translate_point3d(world_point3d *point, world_distance distance, angle theta, angle phi);
198
199 world_point2d *transform_point2d(world_point2d *point, world_point2d *origin, angle theta);
200 world_point3d *transform_point3d(world_point3d *point, world_point3d *origin, angle theta, angle phi);
201
202 /* angle is in [0,NUMBER_OF_ANGLES), or, [0,2�) */
203 // LP change: made this long-distance friendly
204 angle arctangent(int32 x, int32 y);
205
206 void set_random_seed(uint16 seed);
207 uint16 get_random_seed(void);
208 uint16 global_random(void);
209
210 uint16 local_random(void);
211
212 world_distance guess_distance2d(world_point2d *p0, world_point2d *p1);
213 world_distance distance3d(world_point3d *p0, world_point3d *p1);
214 world_distance distance2d(world_point2d *p0, world_point2d *p1); /* calls isqrt() */
215
216 int32 isqrt(uint32 x);
217
218 // LP additions: kludges for doing long-distance calculation
219 // by storing the upper digits in the upper byte of a "flags" value.
220 // These digits are the first 4 of X and Y beyond the short-integer digits.
221
222 void long_to_overflow_short_2d(long_vector2d& LVec, world_point2d& WVec, uint16& flags);
223 void overflow_short_to_long_2d(world_point2d& WVec, uint16& flags, long_vector2d& LVec);
224
225 // Transform that produces a result with this kludge
226 world_point2d *transform_overflow_point2d(world_point2d *point, world_point2d *origin, angle theta, uint16 *flags);
227
228 // Simple copy-overs
long_to_short_2d(long_vector2d & LVec,world_vector2d & WVec)229 static inline void long_to_short_2d(long_vector2d& LVec, world_vector2d&WVec)
230 {
231 WVec.i = static_cast<short>(LVec.i);
232 WVec.j = static_cast<short>(LVec.j);
233 }
short_to_long_2d(world_vector2d & WVec,long_vector2d & LVec)234 static inline void short_to_long_2d(world_vector2d&WVec, long_vector2d& LVec)
235 {
236 LVec.i = WVec.i;
237 LVec.j = WVec.j;
238 }
239
240 #endif
241