2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Render/3dLaser.cpp $
15 * Code to draw 3d looking lasers
18 * Revision 1.3 2002/06/09 04:41:25 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:51 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
28 * 5 7/30/99 7:01p Dave
29 * Dogfight escort gauge. Fixed up laser rendering in Glide.
31 * 4 7/27/99 3:09p Dave
32 * Made g400 work. Whee.
34 * 3 5/27/99 6:17p Dave
35 * Added in laser glows.
37 * 2 10/07/98 10:53a Dave
40 * 1 10/07/98 10:51a Dave
42 * 26 5/13/98 3:10p John
43 * made detail slider for weapon rendering change the distance that lasers
44 * become non-textured. The lowest setting turns off missile trail
47 * 25 5/05/98 11:15p Lawrance
48 * Optimize weapon flyby sound determination
50 * 24 4/10/98 5:20p John
51 * Changed RGB in lighting structure to be ubytes. Removed old
52 * not-necessary 24 bpp software stuff.
54 * 23 3/17/98 3:02p John
55 * made lasers draw as non-textured only on software.
57 * 22 3/17/98 3:01p John
58 * Make thicker lasers not render as polys further away.
60 * 21 2/26/98 3:26p John
61 * Added code to turn off laser rendering
63 * 20 1/29/98 9:46a John
64 * Capped debris length
66 * 19 1/23/98 5:08p John
67 * Took L out of vertex structure used B (blue) instead. Took all small
68 * fireballs out of fireball types and used particles instead. Fixed some
69 * debris explosion things. Restructured fireball code. Restructured
70 * some lighting code. Made dynamic lighting on by default. Made groups
71 * of lasers only cast one light. Made fireballs not cast light.
73 * 18 1/19/98 8:51a John
74 * Did a quick out if both points of laser off same side of view pyramid.
76 * 17 1/06/98 6:18p John
77 * Made debris render as a blur. Had to make g3_draw_laser take tmap
80 * 16 12/15/97 10:09p John
81 * put in some debug laser code.
83 * 15 12/15/97 11:32a John
86 * 14 10/23/97 8:32p John
87 * Increased laser to dot distance
89 * 13 9/20/97 9:45a John
90 * made lasers not draw as pixels as fast as before if viewing from the
94 * 12 8/19/97 11:42p Lawrance
95 * use atan2_safe() instead of atan2()
97 * 11 8/19/97 12:54p Sandeep
98 * Fixed lasers to work in optimized build
100 * 10 6/24/97 6:22p John
101 * added detail flags.
102 * sped up motion debris system a bit.
104 * 9 5/29/97 3:10p John
105 * Took out debug menu.
106 * Made software scaler draw larger bitmaps.
107 * Optimized Direct3D some.
109 * 8 4/29/97 9:55a John
111 * 7 4/22/97 4:11p John
112 * New debug var stuff
114 * 6 3/28/97 6:10p Lawrance
115 * draw lasers so end appears at gun mount tip on first frame
117 * 5 3/06/97 8:48a John
118 * fixed bug with lasers drawing too close.
120 * 4 2/07/97 9:07a John
121 * made lasers not fade by default.
123 * 3 2/03/97 8:01p John
124 * Added debug code to fade lasers out with distance.
126 * 2 12/11/96 12:41p John
127 * Added new code to draw 3d laser using 2d ellipses.
129 * 1 12/11/96 12:13p John
136 #include "3dinternal.h"
137 #include "systemvars.h"
141 DCF_BOOL( lasers, Lasers );
143 // This assumes you have already set a color with gr_set_color or gr_set_color_fast
144 // and a bitmap with gr_set_bitmap. If it is very far away, it draws the laser
145 // as flat-shaded using current color, else textured using current texture.
146 // If max_len is > 1.0, then this caps the length to be no longer than max_len pixels.
147 float g3_draw_laser(vector *headp, float head_width, vector *tailp, float tail_width, uint tmap_flags, float max_len )
153 float headx, heady, headr, tailx, taily, tailr;
158 Assert( G3_count == 1 );
160 g3_rotate_vertex(&pt1,headp);
162 g3_project_vertex(&pt1);
163 if (pt1.flags & PF_OVERFLOW)
166 g3_rotate_vertex(&pt2,tailp);
168 g3_project_vertex(&pt2);
169 if (pt2.flags & PF_OVERFLOW)
172 if ( (pt1.codes & pt2.codes) != 0 ) {
173 // Both off the same side
179 headr = (head_width*Matrix_scale.x*Canv_w2*pt1.sw);
183 tailr = (tail_width*Matrix_scale.x*Canv_w2*pt2.sw);
185 float len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
187 // Cap the length if needed.
188 if ( (max_len > 1.0f) && (len_2d > max_len) ) {
189 float ratio = max_len / len_2d;
191 tailx = headx + ( tailx - headx ) * ratio;
192 taily = heady + ( taily - heady ) * ratio;
193 tailr = headr + ( tailr - headr ) * ratio;
195 len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
198 depth = (pt1.z+pt2.z)*0.5f;
208 float mx, my, w, h1,h2;
210 if ( len_2d < max_r ) {
212 h1 = headr + (max_r-len_2d);
213 if ( h1 > max_r ) h1 = max_r;
214 h2 = tailr + (max_r-len_2d);
215 if ( h2 > max_r ) h2 = max_r;
218 if ( fl_abs(tailx - headx) > 0.01f ) {
219 a = (float)atan2( taily-heady, tailx-headx );
228 a = atan2_safe( taily-heady, tailx-headx );
237 mx = (tailx+headx)/2.0f;
238 my = (taily+heady)/2.0f;
240 // gr_set_color(255,0,0);
241 // g3_draw_line( &pt1, &pt2 );
243 // gr_set_color( 255, 0, 0 );
244 // gr_pixel( fl2i(mx),fl2i(my) );
246 // Draw box with width 'w' and height 'h' at angle 'a' from horizontal
247 // centered around mx, my
249 if ( h1 < 1.0f ) h1 = 1.0f;
250 if ( h2 < 1.0f ) h2 = 1.0f;
258 vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] };
261 if ( depth < 0.0f ) depth = 0.0f;
264 v[0].sx = (-w/2.0f)*ca + (-h1/2.0f)*sa + mx;
265 v[0].sy = (-w/2.0f)*sa - (-h1/2.0f)*ca + my;
272 v[1].sx = (w/2.0f)*ca + (-h2/2.0f)*sa + mx;
273 v[1].sy = (w/2.0f)*sa - (-h2/2.0f)*ca + my;
280 v[2].sx = (w/2.0f)*ca + (h2/2.0f)*sa + mx;
281 v[2].sy = (w/2.0f)*sa - (h2/2.0f)*ca + my;
288 v[3].sx = (-w/2.0f)*ca + (h1/2.0f)*sa + mx;
289 v[3].sy = (-w/2.0f)*sa - (h1/2.0f)*ca + my;
296 if(gr_screen.mode == GR_GLIDE){
297 gr_tmapper(4, vertlist, tmap_flags);
299 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_CORRECT);
305 // Draw a laser shaped 3d looking thing using vertex coloring (useful for things like colored laser glows)
306 // If max_len is > 1.0, then this caps the length to be no longer than max_len pixels
307 float g3_draw_laser_rgb(vector *headp, float head_width, vector *tailp, float tail_width, int r, int g, int b, uint tmap_flags, float max_len )
313 float headx, heady, headr, tailx, taily, tailr;
318 Assert( G3_count == 1 );
320 g3_rotate_vertex(&pt1,headp);
322 g3_project_vertex(&pt1);
323 if (pt1.flags & PF_OVERFLOW)
326 g3_rotate_vertex(&pt2,tailp);
328 g3_project_vertex(&pt2);
329 if (pt2.flags & PF_OVERFLOW)
332 if ( (pt1.codes & pt2.codes) != 0 ) {
333 // Both off the same side
339 headr = (head_width*Matrix_scale.x*Canv_w2*pt1.sw);
343 tailr = (tail_width*Matrix_scale.x*Canv_w2*pt2.sw);
345 float len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
347 // Cap the length if needed.
348 if ( (max_len > 1.0f) && (len_2d > max_len) ) {
349 float ratio = max_len / len_2d;
351 tailx = headx + ( tailx - headx ) * ratio;
352 taily = heady + ( taily - heady ) * ratio;
353 tailr = headr + ( tailr - headr ) * ratio;
355 len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
358 depth = (pt1.z+pt2.z)*0.5f;
368 float mx, my, w, h1,h2;
370 if ( len_2d < max_r ) {
372 h1 = headr + (max_r-len_2d);
373 if ( h1 > max_r ) h1 = max_r;
374 h2 = tailr + (max_r-len_2d);
375 if ( h2 > max_r ) h2 = max_r;
378 if ( fl_abs(tailx - headx) > 0.01f ) {
379 a = (float)atan2( taily-heady, tailx-headx );
388 a = atan2_safe( taily-heady, tailx-headx );
397 mx = (tailx+headx)/2.0f;
398 my = (taily+heady)/2.0f;
400 // gr_set_color(255,0,0);
401 // g3_draw_line( &pt1, &pt2 );
403 // gr_set_color( 255, 0, 0 );
404 // gr_pixel( fl2i(mx),fl2i(my) );
406 // Draw box with width 'w' and height 'h' at angle 'a' from horizontal
407 // centered around mx, my
409 if ( h1 < 1.0f ) h1 = 1.0f;
410 if ( h2 < 1.0f ) h2 = 1.0f;
418 vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] };
421 if ( depth < 0.0f ) depth = 0.0f;
424 v[0].sx = (-w/2.0f)*ca + (-h1/2.0f)*sa + mx;
425 v[0].sy = (-w/2.0f)*sa - (-h1/2.0f)*ca + my;
435 v[1].sx = (w/2.0f)*ca + (-h2/2.0f)*sa + mx;
436 v[1].sy = (w/2.0f)*sa - (-h2/2.0f)*ca + my;
446 v[2].sx = (w/2.0f)*ca + (h2/2.0f)*sa + mx;
447 v[2].sy = (w/2.0f)*sa - (h2/2.0f)*ca + my;
457 v[3].sx = (-w/2.0f)*ca + (h1/2.0f)*sa + mx;
458 v[3].sy = (-w/2.0f)*sa - (h1/2.0f)*ca + my;
468 if(gr_screen.mode == GR_GLIDE){
469 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD);
471 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT);