source: golgotha/src/golg/sky.cc @ 80

Last change on this file since 80 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: 13.9 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 "sky.hh"
10#include "init/init.hh"
11#include "lisp/lisp.hh"
12#include "g1_render.hh"
13#include "r1_api.hh"
14#include "tmanage.hh"
15#include "map_man.hh"
16#include "map.hh"
17#include "loaders/load.hh"
18#include "window/window.hh"
19#include "resources.hh"
20#include "objs/model_id.hh"
21#include "math/vector.hh"
22#include "math/angle.hh"
23#include "math/pi.hh"
24#include "cwin_man.hh"
25#include "gtext_load.hh"
26#include "camera.hh"
27#include "draw_context.hh"
28#include "time/profile.hh"
29#include "r1_clip.hh"
30#include "tick_count.hh"
31#include "lisp/li_class.hh"
32#include "map_vars.hh"
33#include "g1_tint.hh"
34
35li_object_class_member top_cloud_layer("top_cloud_layer"), bottom_cloud_layer("bottom_cloud_layer");
36li_float_class_member li_red("red"), li_green("green"), li_blue("blue"), li_alpha("alpha");
37
38i4_profile_class pf_draw_sky("g1_draw_sky");
39
40i4_array<i4_str *> g1_sky_list(0,16);
41li_object *g1_def_skys(li_object *o, li_environment *env);
42static r1_texture_ref sky_texture("cloud2");
43
44
45
46void scale_copy(i4_image_class *src, i4_image_class *dst, int sx1, int sy1, int sx2, int sy2)
47{
48
49  int dest_x, dest_y;
50  float source_x, source_y;
51  float source_xstep=(float)(sx2-sx1+1) / (float)dst->width();
52  float source_ystep=(float)(sy2-sy1+1) / dst->height();
53
54  i4_draw_context_class c1(0,0, src->width()-1, src->height()-1);
55  i4_draw_context_class c2(0,0, dst->width()-1, dst->height()-1);
56
57  int dest_h=dst->height(), dest_w=dst->width();
58
59  for (source_y=sy1, dest_y=0; dest_y<dest_h; dest_y++,  source_y+=source_ystep)
60  {
61    for (source_x=sx1, dest_x=0; dest_x<dest_w; dest_x++,  source_x+=source_xstep)
62    {
63      w32 color=src->get_pixel(i4_f_to_i(source_x), i4_f_to_i(source_y), c1);
64      dst->put_pixel(dest_x, dest_y, color, c2);
65    }
66  }
67
68}
69
70class g1_sky_class : public i4_init_class
71{
72public:
73  i4_str *current_sky_name;
74  i4_image_class *sky_im;
75  g1_quad_object_class *sky_model;
76  i4_time_class sky_time, start_time;
77
78  void init()
79  {
80    current_sky_name=0;
81    li_add_function("def_skys", g1_def_skys);     
82  }
83
84  void reset()
85  {
86    for (int i=0; i<g1_sky_list.size(); i++)
87      delete g1_sky_list[i];
88 
89    g1_sky_list.clear();
90
91    if (current_sky_name)
92      delete current_sky_name;
93
94    current_sky_name=0;
95  }
96
97  void uninit()
98  {     
99    if (current_sky_name)
100      delete current_sky_name;
101    current_sky_name=0;
102    for (int i=0; i<g1_sky_list.size(); i++)
103      delete g1_sky_list[i];
104    g1_sky_list.uninit();
105  }
106
107  i4_file_class *find_sky_file(i4_const_str fname)
108  {
109    if (fname.null())
110      return 0;
111
112    i4_filename_struct fn;
113    i4_split_path(fname, fn);
114   
115    // try the skys directory first
116    char aname[256];
117    sprintf(aname, "skys/%s.jpg", fn.filename);
118    i4_file_class *fp=i4_open(aname);
119
120    if (fp) return fp;
121
122   
123    // try the driectory the level is in
124    i4_filename_struct lev_split;
125    i4_split_path(g1_get_map()->get_filename(), lev_split);
126   
127    sprintf(aname, "%s/%s.jpg", lev_split.path, fn.filename);
128    fp=i4_open(aname);
129
130
131    if (fp) return fp;
132
133
134    return fp;
135  }
136
137
138  i4_bool update(i4_const_str &sky_name, i4_window_class *w, int use_blits)
139  {     
140    r1_render_api_class *api=g1_render.r_api;
141
142    if (use_blits && sky_im && (sky_im->width()!=w->width() || sky_im->height()!=w->height()*2))
143    {
144      delete current_sky_name;
145      current_sky_name=0;
146    }
147   
148    // see if the sky name has changed, if not then no need to try to load stuff
149    if (current_sky_name && *current_sky_name==sky_name)
150    {
151      if (use_blits)
152        return sky_im ? i4_T : i4_F;
153      else
154        return sky_model ? i4_T : i4_F;
155    }
156
157    // assign the new name and clean up old stuff
158    if (current_sky_name)
159      delete current_sky_name;
160    current_sky_name=new i4_str(sky_name);
161
162
163    if (sky_im)
164    {
165      delete sky_im;
166      sky_im=0;
167    }
168    sky_model=0;
169
170
171
172    if (use_blits)
173    {
174      i4_file_class *fp=find_sky_file(*current_sky_name);
175      i4_image_class *im=0;
176
177      if (!fp)
178      {
179        i4_image_class *images[10];
180        w32 id=r1_get_texture_id(*current_sky_name);
181
182        int t=r1_load_gtext(id, images);
183        if (t)
184        {
185          im=images[0];
186          for (int i=1; i<t; i++)
187            delete images[i];
188        }
189        else return i4_F;
190
191      }
192     
193      if (!im)
194        im=i4_load_image(fp);
195
196      if (!im)
197        return i4_F;
198     
199     
200      sky_im = api->create_compatible_image(w->width(), w->height()*2);
201      if (!sky_im)
202      {
203        delete im;
204        im=0;
205        return i4_F;
206      }
207
208      api->lock_image(sky_im);
209
210
211      scale_copy(im, sky_im, 0,0, im->width()-1, im->height()-1);
212
213      // add black lines for interlace mode
214      if (g1_resources.render_window_expand_mode==R1_COPY_1x1_SCANLINE_SKIP)
215      {
216        i4_draw_context_class context(0,0, sky_im->width()-1, sky_im->height()-1);
217
218        for (int i=0; i<=im->height()-1; i+=2)
219          sky_im->bar(0, i, sky_im->width()-1, i, 0, context);
220      }
221
222      api->unlock_image(sky_im);
223      delete im;
224    }
225    else
226    {
227      char sky_name[200];
228      i4_os_string(*current_sky_name, sky_name,200);
229
230      g1_model_id_type model_id=g1_model_list_man.find_handle("sky");     
231      if (!model_id)
232        return i4_F;
233
234      sky_model=g1_model_list_man.get_model(model_id);
235
236      i4_bool loaded;
237      char sname[256], sname1[256], sname2[256];
238      i4_os_string(*current_sky_name, sname, 256);
239
240      sprintf(sname1, "%s1", sname);
241      sprintf(sname2, "%s2", sname);
242
243
244      r1_texture_handle sky1, sky2;
245
246
247      sky1=api->get_tmanager()->register_texture(sname1, "sky", &loaded);
248      if (!loaded)
249        sky1=sky2=api->get_tmanager()->register_texture(sname, "sky", &loaded);
250      else
251      {
252        sky2=api->get_tmanager()->register_texture(sname2, "sky", &loaded);
253        if (!loaded)
254          sky2=sky1;
255      }
256   
257
258      if (!sky1)   
259        return i4_F;
260
261      for (int i=0; i<sky_model->num_quad; i++)
262      {
263        int tinted=sky_model->quad[i].get_flags(g1_quad_class::TINT);
264       
265        if (!tinted)
266          sky_model->quad[i].material_ref=sky1;
267        else
268          sky_model->quad[i].material_ref=sky2;   
269      }
270    }
271
272    return i4_T;
273  }
274
275} g1_sky;
276
277
278li_object *g1_def_skys(li_object *o, li_environment *env)
279{
280  g1_sky.reset();
281
282  for (o=li_cdr(o,env); o; o=li_cdr(o,env))
283  {
284    char *name=li_string::get(li_eval(li_car(o,env), env),env)->value();
285    g1_render.r_api->get_tmanager()->register_texture(name, "sky name");
286    g1_sky_list.add(new i4_str(name));
287  }
288
289  return 0;
290}
291
292
293int force_blits=0;
294
295
296void generate_poly(i4_3d_vector *points, w16 *indexes,                   
297                   i4_transform_class &transform,
298                   float s, float t,
299                   r1_vert *v,
300                   float r, float g, float b, float a)
301{
302  for (int i=0; i<4; i++)
303  {
304    int x=indexes[i];
305
306    i4_3d_vector p=points[x];
307    transform.transform(p, v[i].v);
308    v[i].v.x*=g1_render.scale_x;
309    v[i].v.y*=g1_render.scale_y;
310    v[i].r=r;
311    v[i].g=g;
312    v[i].b=b;
313    v[i].a=a;
314  }
315   
316  v[0].s=s;      v[0].t=t;
317  v[1].s=s+0.5;  v[1].t=t;
318  v[2].s=s+0.5;  v[2].t=t+0.5;
319  v[3].s=s;      v[3].t=t+0.5;
320}
321                   
322
323
324static float cam_z=8;
325void draw_clouds(g1_camera_info_struct &current_camera,
326                 i4_transform_class &transform,
327                 g1_draw_context_class *context)
328
329{
330  int i,j;
331  r1_vert v[2*2+20], *p;
332 
333 
334  i4_3d_vector pts[4*4], *pt;
335
336  float cloud_scale=15;
337
338  int repeat_length = (int)(cloud_scale*2*16);
339  float start_t=fmod((g1_tick_counter+g1_render.frame_ratio)/2000.0+current_camera.gy/200.0,0.5);
340  float start_s=fmod(current_camera.gx*(1/200.0), 0.5);
341
342  float r[2],g[2],b[2],a[2];
343
344  li_class *bottom_layer=(li_class *)g1_map_vars.vars()->get(bottom_cloud_layer);
345
346  r[0]=bottom_layer->get(li_red);
347  g[0]=bottom_layer->get(li_green);
348  b[0]=bottom_layer->get(li_blue);
349  a[0]=bottom_layer->get(li_alpha);
350   
351  li_class *top_layer=(li_class *)g1_map_vars.vars()->get(top_cloud_layer);
352  r[1]=top_layer->get(li_red);
353  g[1]=top_layer->get(li_green);
354  b[1]=top_layer->get(li_blue);
355  a[1]=top_layer->get(li_alpha);
356
357  for (int k=1; k>=0; k--)
358  {
359
360    pt=pts;
361
362    for (float y=-1.5; y<=1.5; y+=1)
363      for (float x=-1.5; x<=1.5; x+=1, pt++)
364        *pt=i4_3d_vector(x * cloud_scale + current_camera.gx,
365                         y * cloud_scale + current_camera.gy,
366                         cam_z+current_camera.gz*0.9-(fabs(x)+fabs(y))*cloud_scale/8.0+k);
367   
368
369    g1_render.r_api->use_texture(sky_texture.get(), 256,0);
370
371    for (j=0; j<3; j++)
372      for (i=0; i<3; i++)
373      {
374        w16 indexes[4];
375        indexes[0]=i+j*4;
376        indexes[1]=indexes[0]+1;
377        indexes[2]=indexes[0]+5;
378        indexes[3]=indexes[0]+4;
379
380        generate_poly(pts, indexes, transform, start_s, start_t, v, r[k], g[k], b[k], a[k]);
381
382     
383        if (i==0) { v[0].a=0; v[3].a=0; }
384        else if (i==2) { v[1].a=0; v[2].a=0; }
385
386        if (j==0) { v[0].a=0; v[1].a=0; }
387        else if (j==2) { v[2].a=0; v[3].a=0; }
388
389
390       
391
392
393        r1_vert buf1[20], buf2[20], *pv;
394        sw32 t_verts=4;
395        w16 v_index[4]={0,1,2,3};
396        pv=g1_render.r_api->clip_poly(&t_verts, v, v_index, buf1, buf2, 0);
397                   
398        if (t_verts)
399        {
400
401          for (int j=0; j<t_verts; j++)
402          {
403            r1_vert *v = &pv[j];
404
405            float ooz = r1_ooz(v->v.z);           
406         
407            v->px = v->v.x * ooz * g1_render.center_x + g1_render.center_x;
408            v->py = g1_render.center_y + v->v.y * ooz * g1_render.center_y;
409            v->w  = ooz;                 
410          }
411
412          g1_render.r_api->render_poly(t_verts, pv);
413        }
414      }
415   
416
417  }
418}
419
420
421
422void g1_draw_sky(i4_window_class *window,
423                 g1_camera_info_struct &current_camera,
424                 i4_transform_class &transform,
425                 g1_draw_context_class *context)
426               
427
428  pf_draw_sky.start();
429
430  r1_render_api_class *api=g1_render.r_api;
431
432  int use_blits=(api->get_render_device_flags() & R1_SOFTWARE) ? 1 : 0;
433  if (force_blits) use_blits=1;
434  if (g1_get_map()->sky_name &&
435      g1_get_map()->sky_name->null())
436  {
437    delete g1_get_map()->sky_name;
438    g1_get_map()->sky_name=0;
439  }
440 
441  if (g1_get_map()->sky_name &&
442      g1_sky.update(*g1_get_map()->sky_name, window, use_blits))
443  {
444
445    if (use_blits) 
446    {
447      int window_xoff=context->context->xoff, window_yoff=context->context->yoff;
448
449      i4_image_class *sky_im = g1_sky.sky_im;
450
451      i4_normalize_angle(current_camera.ground_rotate);
452      i4_float horz_cap = -current_camera.horizon_rotate;   
453
454      i4_normalize_angle(horz_cap);
455
456      if (horz_cap > 3*i4_pi()/2) horz_cap = 0;
457      if (horz_cap > i4_pi()/2)   horz_cap = i4_pi()/2;
458   
459      sw32 h = sky_im->height() / 2;
460
461      sw32 x_offs = i4_f_to_i(current_camera.ground_rotate * 4 *
462                              sky_im->width() / i4_2pi()) % sky_im->width();
463
464      sw32 y_offs = i4_f_to_i(horz_cap * h/(i4_pi()/2));
465   
466      if (y_offs > h) y_offs = h;
467      if (y_offs < 0) y_offs = 0;
468
469      //y_offs -= (h/4);
470
471      y_offs = h - y_offs;
472     
473      sw32 y2 = y_offs+h-1;
474      if (y2>sky_im->height()-1) y2 = sky_im->height()-1;
475
476      //y cffset must be even for interlaced
477      if (g1_resources.render_window_expand_mode==R1_COPY_1x1_SCANLINE_SKIP)       
478        y_offs = y_offs & (~1);
479
480      if (g1_hurt_tint>0)
481      {
482        // solid red fill
483        i4_color col =
484          (i4_f_to_i(g1_hurt_tint_data[g1_hurt_tint].r*255)<<16) |
485          (i4_f_to_i(g1_hurt_tint_data[g1_hurt_tint].g*255)<<8) |
486          (i4_f_to_i(g1_hurt_tint_data[g1_hurt_tint].b*255));
487       
488        api->clear_area(0,0, window->width()-1, window->height()-1, col, g1_far_z_range()); 
489      }
490      else
491      {
492        // blit sky image
493        api->put_image(sky_im,
494                       x_offs,
495                       0,
496                       0, y_offs,
497                       sky_im->width()-x_offs-1, y2);
498       
499        if (x_offs>0)
500          api->put_image(sky_im,
501                         0,0,
502                         sky_im->width()-x_offs, y_offs,
503                         sky_im->width()-1, y2);
504      }
505    }
506    else
507    {
508      i4_transform_class out, scale, trans;
509      out.identity();
510
511      trans.translate(current_camera.gx, current_camera.gy, -4);
512      out=transform;
513      out.multiply(trans);
514
515      api->set_filter_mode(R1_BILINEAR_FILTERING);
516      api->set_write_mode(  R1_WRITE_COLOR | R1_COMPARE_W );
517      g1_render.render_object(g1_sky.sky_model,
518                              &out,
519                              0,
520                              100,                   
521                              g1_default_player,
522                              0,
523                              0,
524                              0);
525
526      api->set_write_mode(  R1_WRITE_COLOR | R1_WRITE_W | R1_COMPARE_W );
527
528
529      draw_clouds(current_camera, transform, context);
530     
531      api->set_filter_mode(R1_NO_FILTERING);
532    }
533  }
534  else
535    api->clear_area(0,0, window->width()-1, window->height()-1, 0, g1_far_z_range()); 
536
537  pf_draw_sky.stop();
538}
539
Note: See TracBrowser for help on using the repository browser.