]> icculus.org git repositories - taylor/freespace2.git/blob - src/render/3dlaser.cpp
const-char warning fixes
[taylor/freespace2.git] / src / render / 3dlaser.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Render/3dLaser.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Code to draw 3d looking lasers
16  *
17  * $Log$
18  * Revision 1.4  2002/06/17 06:33:10  relnev
19  * ryan's struct patch for gcc 2.95
20  *
21  * Revision 1.3  2002/06/09 04:41:25  relnev
22  * added copyright header
23  *
24  * Revision 1.2  2002/05/07 03:16:51  theoddone33
25  * The Great Newline Fix
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:10  root
28  * Initial import.
29  *
30  * 
31  * 5     7/30/99 7:01p Dave
32  * Dogfight escort gauge. Fixed up laser rendering in Glide.
33  * 
34  * 4     7/27/99 3:09p Dave
35  * Made g400 work. Whee.
36  * 
37  * 3     5/27/99 6:17p Dave
38  * Added in laser glows.
39  * 
40  * 2     10/07/98 10:53a Dave
41  * Initial checkin.
42  * 
43  * 1     10/07/98 10:51a Dave
44  * 
45  * 26    5/13/98 3:10p John
46  * made detail slider for weapon rendering change the distance that lasers
47  * become non-textured.  The lowest setting turns off missile trail
48  * rendering.
49  * 
50  * 25    5/05/98 11:15p Lawrance
51  * Optimize weapon flyby sound determination
52  * 
53  * 24    4/10/98 5:20p John
54  * Changed RGB in lighting structure to be ubytes.  Removed old
55  * not-necessary 24 bpp software stuff.
56  * 
57  * 23    3/17/98 3:02p John
58  * made lasers draw as non-textured only on software.
59  * 
60  * 22    3/17/98 3:01p John
61  * Make thicker lasers not render as polys further away.
62  * 
63  * 21    2/26/98 3:26p John
64  * Added code to turn off laser rendering
65  * 
66  * 20    1/29/98 9:46a John
67  * Capped debris length
68  * 
69  * 19    1/23/98 5:08p John
70  * Took L out of vertex structure used B (blue) instead.   Took all small
71  * fireballs out of fireball types and used particles instead.  Fixed some
72  * debris explosion things.  Restructured fireball code.   Restructured
73  * some lighting code.   Made dynamic lighting on by default. Made groups
74  * of lasers only cast one light.  Made fireballs not cast light.
75  * 
76  * 18    1/19/98 8:51a John
77  * Did a quick out if both points of laser off same side of view pyramid.
78  * 
79  * 17    1/06/98 6:18p John
80  * Made debris render as a blur.  Had to make g3_draw_laser take tmap
81  * flags.
82  * 
83  * 16    12/15/97 10:09p John
84  * put in some debug laser code.
85  * 
86  * 15    12/15/97 11:32a John
87  * New Laser Code
88  * 
89  * 14    10/23/97 8:32p John
90  * Increased laser to dot distance
91  * 
92  * 13    9/20/97 9:45a John
93  * made lasers not draw as pixels as fast as before if viewing from the
94  * side.
95  * 
96  * 
97  * 12    8/19/97 11:42p Lawrance
98  * use atan2_safe() instead of atan2()
99  * 
100  * 11    8/19/97 12:54p Sandeep
101  * Fixed lasers to work in optimized build
102  * 
103  * 10    6/24/97 6:22p John
104  * added detail flags.
105  * sped up motion debris system a bit.
106  * 
107  * 9     5/29/97 3:10p John
108  * Took out debug menu.  
109  * Made software scaler draw larger bitmaps.
110  * Optimized Direct3D some.
111  * 
112  * 8     4/29/97 9:55a John
113  * 
114  * 7     4/22/97 4:11p John
115  * New debug var stuff
116  * 
117  * 6     3/28/97 6:10p Lawrance
118  * draw lasers so end appears at gun mount tip on first frame
119  * 
120  * 5     3/06/97 8:48a John
121  * fixed bug with lasers drawing too close.
122  * 
123  * 4     2/07/97 9:07a John
124  * made lasers not fade by default.
125  * 
126  * 3     2/03/97 8:01p John
127  * Added debug code to fade lasers out with distance.
128  * 
129  * 2     12/11/96 12:41p John
130  * Added new code to draw 3d laser using 2d ellipses.
131  * 
132  * 1     12/11/96 12:13p John
133  *
134  * $NoKeywords: $
135  */
136
137 #include "2d.h"
138 #include "3d.h"
139 #include "3dinternal.h"
140 #include "systemvars.h"
141 #include "key.h"
142
143 int Lasers = 1;
144 DCF_BOOL( lasers, Lasers );
145
146 // This assumes you have already set a color with gr_set_color or gr_set_color_fast
147 // and a bitmap with gr_set_bitmap.  If it is very far away, it draws the laser
148 // as flat-shaded using current color, else textured using current texture.
149 // If max_len is > 1.0, then this caps the length to be no longer than max_len pixels.
150 float g3_draw_laser(vector *headp, float head_width, vector *tailp, float tail_width, uint tmap_flags, float max_len )
151 {
152         if (!Lasers){
153                 return 0.0f;
154         }
155
156         float headx, heady, headr, tailx, taily, tailr;
157         vertex pt1, pt2;
158         float depth;
159         int head_on = 0;
160
161         Assert( G3_count == 1 );
162
163         g3_rotate_vertex(&pt1,headp);
164
165         g3_project_vertex(&pt1);
166         if (pt1.flags & PF_OVERFLOW) 
167                 return 0.0f;
168
169         g3_rotate_vertex(&pt2,tailp);
170
171         g3_project_vertex(&pt2);
172         if (pt2.flags & PF_OVERFLOW) 
173                 return 0.0f;
174
175         if ( (pt1.codes & pt2.codes) != 0 )     {
176                 // Both off the same side
177                 return 0.0f;
178         }
179
180         headx = pt1.sx;
181         heady = pt1.sy;
182         headr = (head_width*Matrix_scale.xyz.x*Canv_w2*pt1.sw);
183
184         tailx = pt2.sx;
185         taily = pt2.sy;
186         tailr = (tail_width*Matrix_scale.xyz.x*Canv_w2*pt2.sw);
187
188         float len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
189
190         // Cap the length if needed.
191         if ( (max_len > 1.0f) && (len_2d > max_len) )   {
192                 float ratio = max_len / len_2d;
193         
194                 tailx = headx + ( tailx - headx ) * ratio;
195                 taily = heady + ( taily - heady ) * ratio;
196                 tailr = headr + ( tailr - headr ) * ratio;
197
198                 len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
199         }
200
201         depth = (pt1.z+pt2.z)*0.5f;
202
203         float max_r  = headr;
204         float a;
205         if ( tailr > max_r ) 
206                 max_r = tailr;
207
208         if ( max_r < 1.0f )
209                 max_r = 1.0f;
210
211         float mx, my, w, h1,h2;
212
213         if ( len_2d < max_r ) {
214
215                 h1 = headr + (max_r-len_2d);
216                 if ( h1 > max_r ) h1 = max_r;
217                 h2 = tailr + (max_r-len_2d);
218                 if ( h2 > max_r ) h2 = max_r;
219
220                 len_2d = max_r;
221                 if ( fl_abs(tailx - headx) > 0.01f )    {
222                         a = (float)atan2( taily-heady, tailx-headx );
223                 } else {
224                         a = 0.0f;
225                 }
226
227                 w = len_2d;
228                 head_on = 1;
229
230         } else {
231                 a = atan2_safe( taily-heady, tailx-headx );
232
233                 w = len_2d;
234
235                 h1 = headr;
236                 h2 = tailr;
237                 head_on = 0;
238         }
239         
240         mx = (tailx+headx)/2.0f;
241         my = (taily+heady)/2.0f;
242
243 //      gr_set_color(255,0,0);
244 //      g3_draw_line( &pt1, &pt2 );
245
246 //      gr_set_color( 255, 0, 0 );
247 //      gr_pixel( fl2i(mx),fl2i(my) );
248
249         // Draw box with width 'w' and height 'h' at angle 'a' from horizontal
250         // centered around mx, my
251
252         if ( h1 < 1.0f ) h1 = 1.0f;
253         if ( h2 < 1.0f ) h2 = 1.0f;
254
255         float sa, ca;
256
257         sa = (float)sin(a);
258         ca = (float)cos(a);
259
260         vertex v[4];
261         vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] };
262
263         float sw;
264         if ( depth < 0.0f ) depth = 0.0f;
265         sw = 1.0f / depth;
266         
267         v[0].sx = (-w/2.0f)*ca + (-h1/2.0f)*sa + mx;
268         v[0].sy = (-w/2.0f)*sa - (-h1/2.0f)*ca + my;
269         v[0].z = pt1.z;
270         v[0].sw = pt1.sw;
271         v[0].u = 0.0f;
272         v[0].v = 0.0f;
273         v[0].b = 191;
274
275         v[1].sx = (w/2.0f)*ca + (-h2/2.0f)*sa + mx;
276         v[1].sy = (w/2.0f)*sa - (-h2/2.0f)*ca + my;
277         v[1].z = pt2.z;
278         v[1].sw = pt2.sw;
279         v[1].u = 1.0f;
280         v[1].v = 0.0f;
281         v[1].b = 191;
282
283         v[2].sx = (w/2.0f)*ca + (h2/2.0f)*sa + mx;
284         v[2].sy = (w/2.0f)*sa - (h2/2.0f)*ca + my;
285         v[2].z = pt2.z;
286         v[2].sw = pt2.sw;
287         v[2].u = 1.0f;
288         v[2].v = 1.0f;
289         v[2].b = 191;
290
291         v[3].sx = (-w/2.0f)*ca + (h1/2.0f)*sa + mx;
292         v[3].sy = (-w/2.0f)*sa - (h1/2.0f)*ca + my;
293         v[3].z = pt1.z;
294         v[3].sw = pt1.sw;
295         v[3].u = 0.0f;
296         v[3].v = 1.0f;
297         v[3].b = 191;
298
299         if(gr_screen.mode == GR_GLIDE){
300                 gr_tmapper(4, vertlist, tmap_flags);    
301         } else {
302                 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_CORRECT);        
303         }
304
305         return depth;
306 }
307
308 // Draw a laser shaped 3d looking thing using vertex coloring (useful for things like colored laser glows)
309 // If max_len is > 1.0, then this caps the length to be no longer than max_len pixels
310 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 )
311 {
312         if (!Lasers){
313                 return 0.0f;
314         }
315
316         float headx, heady, headr, tailx, taily, tailr;
317         vertex pt1, pt2;
318         float depth;
319         int head_on = 0;
320
321         Assert( G3_count == 1 );
322
323         g3_rotate_vertex(&pt1,headp);
324
325         g3_project_vertex(&pt1);
326         if (pt1.flags & PF_OVERFLOW) 
327                 return 0.0f;
328
329         g3_rotate_vertex(&pt2,tailp);
330
331         g3_project_vertex(&pt2);
332         if (pt2.flags & PF_OVERFLOW) 
333                 return 0.0f;
334
335         if ( (pt1.codes & pt2.codes) != 0 )     {
336                 // Both off the same side
337                 return 0.0f;
338         }
339
340         headx = pt1.sx;
341         heady = pt1.sy;
342         headr = (head_width*Matrix_scale.xyz.x*Canv_w2*pt1.sw);
343
344         tailx = pt2.sx;
345         taily = pt2.sy;
346         tailr = (tail_width*Matrix_scale.xyz.x*Canv_w2*pt2.sw);
347
348         float len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
349
350         // Cap the length if needed.
351         if ( (max_len > 1.0f) && (len_2d > max_len) )   {
352                 float ratio = max_len / len_2d;
353         
354                 tailx = headx + ( tailx - headx ) * ratio;
355                 taily = heady + ( taily - heady ) * ratio;
356                 tailr = headr + ( tailr - headr ) * ratio;
357
358                 len_2d = fl_sqrt( (tailx-headx)*(tailx-headx) + (taily-heady)*(taily-heady) );
359         }
360
361         depth = (pt1.z+pt2.z)*0.5f;
362
363         float max_r  = headr;
364         float a;
365         if ( tailr > max_r ) 
366                 max_r = tailr;
367
368         if ( max_r < 1.0f )
369                 max_r = 1.0f;
370
371         float mx, my, w, h1,h2;
372
373         if ( len_2d < max_r ) {
374
375                 h1 = headr + (max_r-len_2d);
376                 if ( h1 > max_r ) h1 = max_r;
377                 h2 = tailr + (max_r-len_2d);
378                 if ( h2 > max_r ) h2 = max_r;
379
380                 len_2d = max_r;
381                 if ( fl_abs(tailx - headx) > 0.01f )    {
382                         a = (float)atan2( taily-heady, tailx-headx );
383                 } else {
384                         a = 0.0f;
385                 }
386
387                 w = len_2d;
388                 head_on = 1;
389
390         } else {
391                 a = atan2_safe( taily-heady, tailx-headx );
392
393                 w = len_2d;
394
395                 h1 = headr;
396                 h2 = tailr;
397                 head_on = 0;
398         }
399         
400         mx = (tailx+headx)/2.0f;
401         my = (taily+heady)/2.0f;
402
403 //      gr_set_color(255,0,0);
404 //      g3_draw_line( &pt1, &pt2 );
405
406 //      gr_set_color( 255, 0, 0 );
407 //      gr_pixel( fl2i(mx),fl2i(my) );
408
409         // Draw box with width 'w' and height 'h' at angle 'a' from horizontal
410         // centered around mx, my
411
412         if ( h1 < 1.0f ) h1 = 1.0f;
413         if ( h2 < 1.0f ) h2 = 1.0f;
414
415         float sa, ca;
416
417         sa = (float)sin(a);
418         ca = (float)cos(a);
419
420         vertex v[4];
421         vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] };
422
423         float sw;
424         if ( depth < 0.0f ) depth = 0.0f;
425         sw = 1.0f / depth;
426         
427         v[0].sx = (-w/2.0f)*ca + (-h1/2.0f)*sa + mx;
428         v[0].sy = (-w/2.0f)*sa - (-h1/2.0f)*ca + my;
429         v[0].z = pt1.z;
430         v[0].sw = pt1.sw;
431         v[0].u = 0.0f;
432         v[0].v = 0.0f;
433         v[0].r = (ubyte)r;
434         v[0].g = (ubyte)g;
435         v[0].b = (ubyte)b;
436         v[0].a = 255;
437
438         v[1].sx = (w/2.0f)*ca + (-h2/2.0f)*sa + mx;
439         v[1].sy = (w/2.0f)*sa - (-h2/2.0f)*ca + my;
440         v[1].z = pt2.z;
441         v[1].sw = pt2.sw;
442         v[1].u = 1.0f;
443         v[1].v = 0.0f;
444         v[1].r = (ubyte)r;
445         v[1].g = (ubyte)g;
446         v[1].b = (ubyte)b;
447         v[1].a = 255;
448
449         v[2].sx = (w/2.0f)*ca + (h2/2.0f)*sa + mx;
450         v[2].sy = (w/2.0f)*sa - (h2/2.0f)*ca + my;
451         v[2].z = pt2.z;
452         v[2].sw = pt2.sw;
453         v[2].u = 1.0f;
454         v[2].v = 1.0f;
455         v[2].r = (ubyte)r;
456         v[2].g = (ubyte)g;
457         v[2].b = (ubyte)b;
458         v[2].a = 255;
459
460         v[3].sx = (-w/2.0f)*ca + (h1/2.0f)*sa + mx;
461         v[3].sy = (-w/2.0f)*sa - (h1/2.0f)*ca + my;
462         v[3].z = pt1.z;
463         v[3].sw = pt1.sw;
464         v[3].u = 0.0f;
465         v[3].v = 1.0f;
466         v[3].r = (ubyte)r;
467         v[3].g = (ubyte)g;
468         v[3].b = (ubyte)b;
469         v[3].a = 255;
470         
471         if(gr_screen.mode == GR_GLIDE){
472                 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD);
473         } else {
474                 gr_tmapper(4, vertlist, tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT);
475         }       
476
477         return depth;
478 }
479