source: golgotha/src/golg/objs/shockwave.cc

Last change on this file was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 9.8 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "g1_object.hh"
10#include "math/num_type.hh"
11#include "math/pi.hh"
12#include "saver.hh"
13#include "map.hh"
14#include "g1_render.hh"
15#include "object_definer.hh"
16#include "dll/dll.hh"
17#include "map_man.hh"
18#include "math/pi.hh"
19
20#include "objs/shockwave.hh"
21#include "objs/explosion1.hh"
22#include "objs/debris.hh"
23#include "map_vert.hh"
24#include "sound/sfx_id.hh"
25
26g1_object_definer<g1_shockwave_class>
27g1_shockwave_def("shockwave", g1_object_definition_class::EDITOR_SELECTABLE);
28                                                     
29
30S1_SFX_DISTANCE(explode_sfx, "explosion/super_mortar.wav", S1_3D | S1_STREAMED, 100, 50);
31
32g1_shockwave_class::g1_shockwave_class(g1_object_type id,
33                                       g1_loader_class *fp)
34  : g1_object_class(id, fp), vert_map(0)
35
36  if (fp && fp->check_version(DATA_VERSION))
37  {
38    fp->read_format("ff2", &strength, &focal_radius, &radius); 
39    alloc_vert_map();
40    fp->end_version(I4_LF);
41  }
42  else
43  {
44    radius=5;
45    strength=1;
46    focal_radius=0;
47    alloc_vert_map();
48  }
49
50  draw_params.setup("shockwave");
51}
52
53void g1_shockwave_class::save(g1_saver_class *fp)
54{
55  g1_object_class::save(fp); 
56  fp->start_version(DATA_VERSION); 
57  fp->write_format("ff2", &strength, &focal_radius, &radius); 
58  fp->end_version();
59}
60
61g1_shockwave_class::~g1_shockwave_class()
62{
63  if (vert_map)
64    i4_free(vert_map);
65}
66
67void g1_shockwave_class::alloc_vert_map()
68{
69  if (vert_map)
70    i4_free(vert_map);
71   
72  int d=2*radius+1;
73  vert_map=(vert_offset *)i4_malloc(sizeof(vert_offset) * d*d, "");
74}
75
76void g1_shockwave_class::setup(const i4_3d_vector &pos,  // starting position (center)
77                               float _strength,           // maximum ground distortion
78                               w16 _radius)               // maximum radius in game units
79
80{
81  g1_map_class *map=g1_get_map();
82 
83  x=lx=pos.x;
84  y=ly=pos.y;
85  h=lh=pos.z;
86
87  strength=_strength;
88  radius=_radius;
89  focal_radius=0;
90  alloc_vert_map();
91
92  red_intensity=1.0;
93  green_intensity=1.0;
94  blue_intensity=0;
95
96  if (occupy_location())
97  {
98    request_think();
99    g1_explosion1_class *explosion = NULL;
100   
101    explosion = (g1_explosion1_class *)g1_create_object(g1_get_object_type("explosion1"));
102    if (explosion)
103      explosion->setup(x,y,h, g1_explosion1_class::MAKE_SPHERE);
104
105    g1_debris_class *debris = NULL;
106    debris = (g1_debris_class *)g1_create_object(g1_get_object_type("debris"));
107    if (debris) debris->setup(x,y,h, g1_debris_class::RING_CHUNKS);
108    debris = (g1_debris_class *)g1_create_object(g1_get_object_type("debris"));
109    if (debris) debris->setup(x,y,h, g1_debris_class::RING_CHUNKS);
110    debris = (g1_debris_class *)g1_create_object(g1_get_object_type("debris"));
111    if (debris) debris->setup(x,y,h, g1_debris_class::RING_CHUNKS);
112
113    explode_sfx.play(x,y,h);
114  }
115}
116
117
118
119i4_bool g1_shockwave_class::occupy_location()
120{
121  if (get_flag(MAP_OCCUPIED) || !vert_map)
122    return i4_T;
123
124 
125  if (g1_object_class::occupy_location())
126  {
127 
128    sw32 _ix = i4_f_to_i(x),
129      _iy = i4_f_to_i(y); 
130
131    float oor = 1.f/(float)radius;
132
133    vert_offset *vo = vert_map;
134
135    sw32 x_left,x_right,y_top,y_bottom;
136 
137    sw32 wx = g1_get_map()->width();
138    sw32 wy = g1_get_map()->height();
139 
140    x_left   = _ix - radius; if (x_left<0)     x_left=0;
141    x_right  = _ix + radius; if (x_right>wx-1)  x_right=wx-1;
142    y_top    = _iy - radius; if (y_top<0)      y_top=0;
143    y_bottom = _iy + radius; if (y_bottom>wy-1) y_bottom=wy-1;
144 
145    sw32 ix,iy;
146
147    for (iy=y_top; iy<=y_bottom; iy++)
148    {
149      g1_map_vertex_class *v = g1_get_map()->vertex(x_left, iy);
150
151      for (ix=x_left; ix<=x_right; ix++, vo++, v++)
152      {
153        i4_3d_vector dir = i4_3d_vector(x-ix, y-iy, h - v->get_height());
154
155        i4_float dist  = dir.length();
156        i4_float odist = 1.f/dist;
157
158//         float t=dist * oor;
159        float alpha=fabs((dist - focal_radius)*2.0);
160        float multiplier=2 / (alpha*alpha+1);
161        if (multiplier>1.0) multiplier=1.0;
162        float new_height=multiplier*strength;
163
164        sw32 new_height_value = i4_f_to_i(new_height/0.05);
165
166        if (new_height_value>255)
167          new_height_value=255;
168        else if (new_height_value<0)
169          new_height_value=0;
170     
171        vo->displacement=new_height_value;     
172
173        v->height+=vo->displacement;
174        v->light_sum=0x80000000;
175        v->normal=0x8000;
176
177        w16 old_rgb=v->dynamic_light;
178        sw32 r,g,b, or,og,ob;
179        r=i4_f_to_i(red_intensity*multiplier*255);
180        g=i4_f_to_i(green_intensity*multiplier*255);
181        b=i4_f_to_i(blue_intensity*multiplier*255);
182       
183        or=(old_rgb>>16)&255;              // grab the old light values
184        og=(old_rgb>>8)&255;
185        ob=(old_rgb)&255;
186       
187        if (r+or>255) r=255-or;           // adjust for overflow
188        if (g+og>255) g=255-og;
189        if (b+ob>255) b=255-ob;
190
191        vo->color = (r<<16) | (g<<8) | b;
192        v->dynamic_light += vo->color;
193      }
194    }
195
196    request_think();
197
198    return i4_T;
199  }
200  else return i4_F;
201}
202
203
204void g1_shockwave_class::unoccupy_location()
205{
206  if (get_flag(MAP_OCCUPIED) && vert_map)
207  {
208    g1_object_class::unoccupy_location();
209   
210    sw32 _ix = i4_f_to_i(x),
211         _iy = i4_f_to_i(y);
212
213    vert_offset *vo=vert_map;
214
215    sw32 x_left,x_right,y_top,y_bottom;
216    sw32 w = g1_get_map()->width();
217    sw32 h = g1_get_map()->height();
218
219    x_left   = _ix - radius; if (x_left<0)     x_left=0;
220    x_right  = _ix + radius; if (x_right>w-1)  x_right=w-1;
221    y_top    = _iy - radius; if (y_top<0)      y_top=0;
222    y_bottom = _iy + radius; if (y_bottom>h-1) y_bottom=h-1; 
223
224    sw32 ix,iy;
225
226    for (iy=y_top; iy<=y_bottom; iy++)
227    {
228      g1_map_vertex_class *v=g1_get_map()->vertex(x_left, iy);
229
230      for (ix=x_left; ix<=x_right; ix++, vo++, v++)
231      {
232        v->height-=vo->displacement;
233        v->dynamic_light-=vo->color;
234        v->light_sum=0x80000000;
235        v->normal=0x8000;
236      }
237    }
238  }
239}
240
241
242void g1_shockwave_class::think()
243{
244  grab_old();
245  unoccupy_location();
246  strength *= 0.92;
247  focal_radius += 0.3;
248  red_intensity *= 0.95;
249  green_intensity *= 0.80;
250
251  if (strength<0.05)
252    request_remove();
253  else
254  {
255    occupy_location();
256    request_think();
257  }
258}
259
260void fast_transform(i4_transform_class *t,const i4_3d_vector &src, r1_3d_point_class &dst);
261
262void g1_shockwave_class::draw(g1_draw_context_class *context)
263{   
264  //g1_model_draw(this, draw_params, context);
265#if 0
266  sw32     frequency = 4;
267 
268  i4_float ratio = (1.f / (float)frequency) * i4_interpolate((g1_tick_counter & (frequency-1)),
269                                                              (g1_tick_counter & (frequency-1))+1,
270                                                               g1_render.frame_ratio);
271  if (g1_tick_counter & frequency)
272    ratio = 1-ratio;
273
274  i4_float start_a,start_r,start_g,start_b;
275  i4_float end_a,  end_r,  end_g,  end_b;
276
277  start_a = i4_interpolate(1,0.5,ratio);
278  start_r = 1;
279  start_g = i4_interpolate(0,1,ratio);
280  start_b = 0;
281     
282  end_a   = i4_interpolate(0.5,1,ratio);
283  end_r   = 1;
284  end_g   = i4_interpolate(1,0,ratio);
285  end_b   = 0;
286
287  i4_3d_vector start_point = i4_3d_vector(x,y,h);
288  i4_3d_vector end_point   = i4_3d_vector(x,y,h+20);
289
290  r1_3d_point_class t_start_point, t_end_point;
291     
292  fast_transform(context->transform, start_point, t_start_point);
293  fast_transform(context->transform, end_point,   t_end_point);
294   
295  t_start_point.x *= g1_render.scale_x;
296  t_start_point.y *= g1_render.scale_y;
297
298  t_end_point.x   *= g1_render.scale_x;
299  t_end_point.y   *= g1_render.scale_y;
300
301  i4_3d_vector v;
302
303  v = i4_3d_vector(t_end_point.x - t_start_point.x, t_end_point.y - t_start_point.y, t_end_point.z - t_start_point.z);
304   
305  r1_vert      points[4];
306  i4_3d_vector norm;
307
308  norm.cross((i4_3d_vector &)t_start_point, v);
309  norm.normalize();
310  norm *= 2;
311   
312  points[0].v.x = t_start_point.x + norm.x;
313  points[0].v.y = t_start_point.y + norm.y;
314  points[0].v.z = t_start_point.z + norm.z;
315  points[0].a   = start_a;
316  points[0].r   = start_r;
317  points[0].g   = start_g;
318  points[0].b   = start_b;
319
320  points[1].v.x = t_start_point.x - norm.x;
321  points[1].v.y = t_start_point.y - norm.y;
322  points[1].v.z = t_start_point.z - norm.z;
323  points[1].a   = start_a;
324  points[1].r   = start_r;
325  points[1].g   = start_g;
326  points[1].b   = start_b;
327
328  norm.cross((i4_3d_vector &)t_end_point, v);
329  norm.normalize();
330  norm *= 2;
331   
332  points[2].v.x = t_end_point.x - norm.x;
333  points[2].v.y = t_end_point.y - norm.y;
334  points[2].v.z = t_end_point.z - norm.z;
335  points[2].a   = end_a;
336  points[2].r   = end_r;
337  points[2].g   = end_g;
338  points[2].b   = end_b;
339           
340  points[3].v.x = t_end_point.x + norm.x;
341  points[3].v.y = t_end_point.y + norm.y;
342  points[3].v.z = t_end_point.z + norm.z;
343  points[3].a   = end_a;
344  points[3].r   = end_r;
345  points[3].g   = end_g;
346  points[3].b   = end_b;
347
348  g1_post_draw_quad_class p;
349
350  p.vert_ref[0] = g1_render.add_post_draw_vert(points[0]);
351  p.vert_ref[1] = g1_render.add_post_draw_vert(points[1]);
352  p.vert_ref[2] = g1_render.add_post_draw_vert(points[2]);
353  p.vert_ref[3] = g1_render.add_post_draw_vert(points[3]);
354   
355  g1_render.add_post_draw_quad(p);
356#endif
357}
358
Note: See TracBrowser for help on using the repository browser.