1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 #ifndef _3D_H
12 #define _3D_H
13 
14 #include "math/vecmat.h"
15 #include "graphics/tmapper.h"
16 #include "graphics/2d.h"
17 #include "graphics/grbatch.h"
18 #include "camera/camera.h"
19 
20 //flags for point structure
21 #define PF_PROJECTED 	 1	//has been projected, so sx,sy valid
22 #define PF_OVERFLOW		 2	//can't project
23 #define PF_TEMP_POINT	 4	//created during clip
24 
25 //clipping codes flags
26 #define CC_OFF_LEFT	1
27 #define CC_OFF_RIGHT	2
28 #define CC_OFF_BOT	4
29 #define CC_OFF_TOP	8
30 #define CC_OFF_USER	16
31 #define CC_BEHIND		0x80
32 
33 // Combo!
34 #define CC_OFF			(CC_OFF_LEFT | CC_OFF_RIGHT | CC_OFF_BOT | CC_OFF_TOP | CC_OFF_USER | CC_BEHIND)
35 
36 /**
37  * Start the frame. Pass non-zero to enable zbuffering
38  */
39 #define g3_start_frame(zbuffer_flag) g3_start_frame_func(zbuffer_flag, __FILE__, __LINE__ )
40 
41 /**
42  * Use the g3_start_frame macro instead of calling this directly.
43  */
44 extern void g3_start_frame_func(int zbuffer_flag, char * filename, int lineno);
45 
46 /**
47  * End the frame
48  */
49 #define g3_end_frame() g3_end_frame_func( __FILE__, __LINE__ )
50 extern void g3_end_frame_func(char *filename, int lineno);
51 
52 /**
53  * Currently in frame?
54  */
55 extern int g3_in_frame();
56 
57 /**
58  * Set view from x,y,z & p,b,h, zoom.  Must call one of g3_set_view_*()
59  */
60 void g3_set_view_angles(vec3d *view_pos,angles *view_orient,float zoom);
61 
62 /**
63  * Set view from camera
64  */
65 void g3_set_view(camera *cam);
66 
67 /**
68  * Set view from x,y,z, viewer matrix, and zoom.  Must call one of g3_set_view_*()
69  */
70 void g3_set_view_matrix(vec3d *view_pos,matrix *view_matrix,float zoom);
71 
72 // Never set these!
73 extern matrix		View_matrix;		// The matrix to convert local coordinates to screen
74 extern vec3d		View_position;		// The offset to convert local coordinates to screen
75 
76 extern matrix		Light_matrix;		// Used to rotate world points into current local coordinates
77 extern vec3d		Light_base;			// Used to rotate world points into current local coordinates
78 
79 extern matrix		Eye_matrix;			// Where the viewer's eye is pointing in World coordinates
80 extern vec3d		Eye_position;		// Where the viewer's eye is at in World coordinates
81 extern float		Eye_fov;			// What the viewer's FOV is
82 
83 extern vec3d Object_position;
84 extern matrix	Object_matrix;			// Where the opject is pointing in World coordinates
85 
86 extern float Proj_fov;					// Projection matrix fov (for HT&L)
87 
88 /**
89  * Draw a horizon
90  */
91 void g3_draw_horizon(int sky_color,int ground_color);
92 
93 /**
94  * Draws a line representing the horizon
95  */
96 void g3_draw_horizon_line();
97 
98 /**
99  * Get vectors that are edge of horizon
100  */
101 int g3_compute_sky_polygon(float *points_2d,vec3d *vecs);
102 
103 /**
104  * Instance at specified point with specified orientation
105  */
106 void g3_start_instance_matrix(vec3d *pos,matrix *orient, bool set_api = true);
107 
108 /**
109  * Instance at specified point with specified orientation
110  */
111 void g3_start_instance_angles(vec3d *pos,angles *orient);
112 
113 /**
114  * Pops the old context
115  */
116 void g3_done_instance(bool set_api = false);
117 
118 /**
119  * Get current field of view.  Fills in angle for x & y
120  */
121 void g3_get_FOV(float *fov_x,float *fov_y);
122 
123 /**
124  * Get zoom.
125  *
126  * For a given window size, return the zoom which will achieve
127  * the given FOV along the given axis.
128  */
129 float g3_get_zoom(char axis,float fov,int window_width,int window_height);
130 
131 /**
132  * Returns the normalized, unscaled view vectors
133  */
134 void g3_get_view_vectors(vec3d *forward,vec3d *up,vec3d *right);
135 
136 /**
137  * Returns true if a plane is facing the viewer.
138  *
139  * Takes the unrotated surface normal of the plane, and a point on it.  The normal need not be normalized
140  */
141 int g3_check_normal_facing(vec3d *v,vec3d *norm);
142 
143 /**
144  * Returns codes_and & codes_or of a list of points numbers
145  */
146 ccodes g3_check_codes(int nv,vertex **pointlist);
147 
148 /**
149  * Rotates a point. returns codes.  does not check if already rotated
150  */
151 ubyte g3_rotate_vertex(vertex *dest,vec3d *src);
152 
153 /**
154  * Same as above, only ignores the current instancing
155  */
156 ubyte g3_rotate_vertex_popped(vertex *dest,vec3d *src);
157 
158 /**
159  * Use this for stars, etc
160  */
161 ubyte g3_rotate_faraway_vertex(vertex *dest,vec3d *src);
162 
163 /**
164  * Projects a point
165  */
166 int g3_project_vertex(vertex *point);
167 
168 /**
169  * Projects a vector
170  */
171 ubyte g3_project_vector(vec3d *p, float *sx, float *sy );
172 
173 /**
174  * Rotates a point.
175  * @return Returns codes.
176  */
177 ubyte g3_rotate_vector(vec3d *dest,vec3d *src);
178 
179 /**
180  * Codes a vector.
181  * @return Returns the codes of a point.
182  */
183 ubyte g3_code_vector(vec3d * p);
184 
185 /**
186  * Calculate the depth of a point - returns the z coord of the rotated point
187  */
188 float g3_calc_point_depth(vec3d *pnt);
189 
190 /**
191  * From a 2d point, compute the vector through that point
192  */
193 void g3_point_to_vec(vec3d *v,int sx,int sy);
194 
195 /**
196  * From a 2d point, compute the vector through that point.
197  *
198  * This can be called outside of a g3_start_frame/g3_end_frame
199  * pair as long g3_start_frame was previously called.
200  */
201 void g3_point_to_vec_delayed(vec3d *v,int sx,int sy);
202 
203 /*
204  * Code a point. Fills in the p3_codes field of the point, and returns the codes
205  */
206 ubyte g3_code_vertex(vertex *point);
207 
208 vec3d *g3_rotate_delta_x(vec3d *dest,float dx);
209 vec3d *g3_rotate_delta_y(vec3d *dest,float dy);
210 vec3d *g3_rotate_delta_z(vec3d *dest,float dz);
211 vec3d *g3_rotate_delta_vec(vec3d *dest,vec3d *src);
212 ubyte g3_add_delta_vec(vertex *dest,vertex *src,vec3d *deltav);
213 
214 /**
215  * Draw a polygon.
216  *
217  * Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture.
218  * @return Returns 1 if off screen, 0 if drawn
219  */
220 int g3_draw_poly(int nv,vertex **pointlist,uint tmap_flags);
221 
222 int g3_draw_polygon(vec3d *pos, matrix *ori, float width, float height, int tmap_flags = TMAP_FLAG_TEXTURED);
223 int g3_draw_polygon(vec3d *pos, vec3d *norm, float width, float height, int tmap_flags = TMAP_FLAG_TEXTURED);
224 
225 /**
226  * Draw a polygon.
227  *
228  * Same as g3_draw_poly, but it bashes sw to a constant value
229  * for all vertexes.  Needs to be done after clipping to get them all.
230  *
231  * Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture.
232  * @return Returns 1 if off screen, 0 if drawn
233  */
234 int g3_draw_poly_constant_sw(int nv,vertex **pointlist,uint tmap_flags, float constant_sw);
235 
236 /**
237  * Like g3_draw_poly(), but checks to see if facing.
238  *
239  * If surface normal is NULL, this routine must compute it, which will be slow.
240  * It is better to pre-compute the normal, and pass it to this function.
241  * When the normal is passed, this function works like g3_check_normal_facing() plus g3_draw_poly().
242  *
243  * Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture.
244  * @return Returns -1 if not facing, 1 if off screen, 0 if drawn
245  */
246 int g3_draw_poly_if_facing(int nv,vertex **pointlist,uint tmap_flags,vec3d *norm,vec3d *pnt);
247 
248 /**
249  * Draws a line.
250  *
251  * @param p0 First point
252  * @param p1 Second point
253  */
254 int g3_draw_line(vertex *p0,vertex *p1);
255 
256 /**
257  * Draws a polygon always facing the viewer.
258  * Compute the corners of a rod.  fills in vertbuf.
259  * Verts has any needs uv's or l's or can be NULL if none needed.
260  */
261 int g3_draw_rod(vec3d *p0,float width1,vec3d *p1,float width2, vertex * verts, uint tmap_flags);
262 
263 /**
264  * Draws a bitmap with the specified 3d width & height
265  *
266  * Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture.
267  * @return Returns 1 if off screen, 0 if drawn
268  *
269  * If bitmap is not square, rad will be the 3d size of the smallest dimension.
270  * orient flips the bitmap in some way.  Pass 0 for normal or else pass a
271  * random nuber between 0 and 7, inclusive.
272  */
273 int g3_draw_bitmap(vertex *pos,int orient, float radius, uint tmap_flags, float depth = 0.0f);
274 
275 /**
276  * Get bitmap dims onscreen as if g3_draw_bitmap() had been called
277  */
278 int g3_get_bitmap_dims(int bitmap, vertex *pos, float radius, int *x, int *y, int *w, int *h, int *size);
279 
280 /**
281  * Draw a sortof sphere - i.e., the 2d radius is proportional to the 3d
282  * radius, but not to the distance from the eye.  Uses the current 2d color.
283  */
284 int g3_draw_sphere(vertex *pnt,float rad);
285 
286 /**
287  * Same as g3_draw_sphere, but you pass a vector and this rotates
288  * and projects it and then call g3_draw_sphere.
289  */
290 int g3_draw_sphere_ez(vec3d *pnt,float rad);
291 
292 /**
293  * Draw a laser shaped 3d looking thing.
294  *
295  * If max_len is > 1.0, then this caps the length to be no longer than max_len pixels
296  */
297 float g3_draw_laser(vec3d *headp, float head_width, vec3d *tailp, float tail_width, uint tmap_flags = TMAP_FLAG_TEXTURED, float max_len = 0.0f );
298 
299 /**
300  * Draw a laser shaped 3d looking thing using vertex coloring (useful for things like colored laser glows)
301  *
302  * If max_len is > 1.0, then this caps the length to be no longer than max_len pixels
303  */
304 float g3_draw_laser_rgb(vec3d *headp, float head_width, vec3d *tailp, float tail_width, int r, int g, int b, uint tmap_flags = TMAP_FLAG_TEXTURED | TMAP_FLAG_RGB, float max_len = 0.0f );
305 
306 /**
307  * Draw a bitmap that is always facing, but rotates.
308  *
309  * If bitmap is not square, rad will be the 3d size of the smallest dimension.
310  */
311 int g3_draw_rotated_bitmap(vertex *pnt,float angle, float radius, uint tmap_flags, float depth = 0.0f);
312 
313 /**
314  * Draw a perspective bitmap based on angles and radius
315  */
316 int g3_draw_perspective_bitmap(angles *a, float scale_x, float scale_y, int div_x, int div_y, uint tmap_flags);
317 
318 /**
319  * Draw a 2D shield icon w/ 6 points
320  */
321 void g3_draw_2d_shield_icon(const coord2d coords[6], const int r, const int g, const int b, const int a);
322 
323 /**
324  * Draw a 2D rectangle
325  */
326 void g3_draw_2d_rect(int x, int y, int w, int h, int r, int g, int b, int a);
327 
328 /**
329  * Draw a 2d bitmap on a poly
330  */
331 int g3_draw_2d_poly_bitmap(float x, float y, float w, float h, uint additional_tmap_flags = 0);
332 
333 /**
334  * Enables clipping with an arbritary plane.
335  *
336  * This will be on until g3_stop_clip_plane is called or until next frame.
337  * The points passed should be relative to the instance. Probably
338  * that means world coordinates.
339  *
340  * This works like any other clip plane... if this is enabled and you
341  * rotate a point, the CC_OFF_USER bit will be set in the clipping codes.
342  * It is completely handled by most g3_draw primitives, except maybe lines.
343  *
344  * As far as performance, when enabled, it will slow down each point
345  * rotation (or g3_code_vertex call) by a vec3d subtraction and dot
346  * product.   It won't slow anything down for polys that are completely
347  * clipped on or off by the plane, and will slow each clipped polygon by
348  * not much more than any other clipping we do.
349  */
350 void g3_start_user_clip_plane( vec3d *plane_point, vec3d *plane_normal );
351 
352 /**
353  * Stops arbritary plane clipping
354  */
355 void g3_stop_user_clip_plane();
356 
357 ubyte g3_transfer_vertex(vertex *dest, vec3d *src);
358 
359 int g3_draw_2d_poly_bitmap_list(bitmap_2d_list* b_list, int n_bm, uint additional_tmap_flags);
360 int g3_draw_2d_poly_bitmap_rect_list(bitmap_rect_list* b_list, int n_bm, uint additional_tmap_flags);
361 
362 /**
363  * Draw a line in HTL mode without having to go through the rotate/project stuff
364  */
365 void g3_draw_htl_line(vec3d *start, vec3d *end);
366 
367 /**
368  * Draw a sphere mode without having to go through the rotate/project stuff
369  */
370 void g3_draw_htl_sphere(vec3d *position, float radius);
371 
372 /**
373  * Flash ball
374  *
375  * A neat looking ball of rays that move around and look all energetic and stuff
376  */
377 struct flash_beam{
378 	vertex start;
379 	vertex end;
380 	float width;
381 };
382 
383 class flash_ball{
384 	flash_beam *ray;
385 	vec3d center;
386 	int n_rays;
387 	static geometry_batcher batcher;
388 	void parse_bsp(int offset, ubyte *bsp_data);
389 	void defpoint(int off, ubyte *bsp_data);
390 
391 public:
392 	flash_ball(int number, float min_ray_width, float max_ray_width = 0, vec3d* dir = &vmd_zero_vector, vec3d*pcenter = &vmd_zero_vector, float outer = PI2, float inner = 0.0f, ubyte max_r = 255, ubyte max_g = 255, ubyte max_b = 255, ubyte min_r = 255, ubyte min_g = 255, ubyte min_b = 255)
ray(NULL)393 		:ray(NULL),n_rays(0)
394 		{initialize(number, min_ray_width, max_ray_width , dir , pcenter , outer , inner , max_r , max_g , max_b , min_r , min_g ,min_b);}
~flash_ball()395 	~flash_ball(){if(ray)vm_free(ray);}
396 
397 	void initialize(int number, float min_ray_width, float max_ray_width = 0, vec3d* dir = &vmd_zero_vector, vec3d*pcenter = &vmd_zero_vector, float outer = PI2, float inner = 0.0f, ubyte max_r = 255, ubyte max_g = 255, ubyte max_b = 255, ubyte min_r = 255, ubyte min_g = 255, ubyte min_b = 255);
398 	void initialize(ubyte *bsp_data, float min_ray_width, float max_ray_width = 0, vec3d* dir = &vmd_zero_vector, vec3d*pcenter = &vmd_zero_vector, float outer = PI2, float inner = 0.0f, ubyte max_r = 255, ubyte max_g = 255, ubyte max_b = 255, ubyte min_r = 255, ubyte min_g = 255, ubyte min_b = 255);
399 	void render(float rad, float intinsity, float life);
400 };
401 #endif
402