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