source: golgotha/src/golg/objs/light_o.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: 6.4 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 "objs/light_o.hh"
10#include "saver.hh"
11#include "objs/model_draw.hh"
12#include "map.hh"
13#include "math/num_type.hh"
14#include "object_definer.hh"
15#include "map_man.hh"
16#include "flare.hh"
17#include "time/profile.hh"
18#include "map_vert.hh"
19
20static i4_profile_class pf_light_occupy("light::occupy"), pf_light_unoccupy("light::unoccupy");
21
22g1_object_type g1_lightbulb_type;
23void g1_light_object_init();
24
25g1_object_definer<g1_light_object_class>
26g1_light_object_def("lightbulb",
27                    g1_object_definition_class::EDITOR_SELECTABLE,
28                    g1_light_object_init);
29
30void g1_light_object_init()
31{
32  g1_lightbulb_type = g1_light_object_def.type;
33}
34
35
36void g1_light_object_class::setup(float _x, float _y, float _h,
37                                  float _r, float _g, float _b, float _white,
38                                  float min_light_contribute,
39                                  float linear_contribute,
40                                  float geometric_contribute)
41{
42  r=_r;
43  g=_g;
44  b=_b;
45  x=lx=_x;
46  y=ly=_y;
47  h=lh=_h;
48
49  int occ=get_flag(MAP_OCCUPIED);
50
51  if (occ)
52    unoccupy_location();
53
54  if (add_intensities)
55    i4_free(add_intensities);
56
57
58  c1=min_light_contribute;
59  c2=linear_contribute;
60  c3=geometric_contribute;
61
62  if (c3<0.0016)  // maximum radius is 25 squares for now
63    c3=0.0016;
64
65  change_radius=i4_f_to_i(sqrt((32-c1)/c3));
66 
67  sw32 w=change_radius*2+1,h=change_radius*2+1;
68
69  add_intensities=(w32 *)i4_malloc(w*h*sizeof(w32),
70                                   "light map restore"); 
71 
72  if (occ)
73    occupy_location();
74 
75}
76
77g1_light_object_class::~g1_light_object_class()
78{
79  if (add_intensities)
80    i4_free(add_intensities);
81}
82
83g1_light_object_class::g1_light_object_class(g1_object_type id,
84                                             g1_loader_class *fp)
85  : g1_object_class(id,fp)
86{
87  add_intensities=0;
88
89  if (fp && fp->check_version(DATA_VERSION))
90  {
91    float _r, _g, _b, _white, _c1, _c2, _c3;
92    fp->read_format("fffffff", &_r, &_g, &_b, &_white, &_c1, &_c2, &_c3);
93    setup(x,y,h, _r, _g, _b, _white, _c1, _c2, _c3);
94
95    fp->end_version(I4_LF);
96  }
97  else
98  {
99    r=g=b=1;
100    white=1;   
101    c1=0.1;    c2=0.25;    c3=0.5;   
102    h=2;
103  }
104
105  draw_params.setup("lightbulb");
106}
107
108
109void g1_light_object_class::save(g1_saver_class *fp)
110{
111  g1_object_class::save(fp);
112  fp->start_version(DATA_VERSION);
113  fp->write_format("fffffff", &r,&g,&b, &white, &c1,&c2,&c3);
114  fp->end_version();
115}
116
117void g1_light_object_class::draw(g1_draw_context_class *context)
118
119  g1_editor_model_draw(this, draw_params, context);
120}
121
122
123void g1_light_object_class::move(float nx, float ny, float nh)
124{
125  unoccupy_location();
126  lx=x; ly=y; lh=h;
127  x=nx; y=ny; h=nh;
128
129  occupy_location();
130}
131
132
133void g1_light_object_class::think()
134{
135}
136
137i4_bool g1_light_object_class::occupy_location()
138{
139  if (!add_intensities)
140  {
141    i4_warning("call light::setup before occupy_location");
142   
143    return i4_F;
144  }
145 
146  pf_light_occupy.start();
147  if (g1_object_class::occupy_location())
148  {
149
150   
151    sw32 ix=i4_f_to_i(x), iy=i4_f_to_i(y);
152    w32 *a=add_intensities;
153
154    for (int ty=-change_radius+iy; ty<=change_radius+iy; ty++)
155    {
156      sw32 start_x=ix-change_radius;
157      if (start_x<0) start_x=0;
158      g1_map_vertex_class *v=g1_get_map()->vertex(start_x,ty);
159
160      for (int tx=-change_radius+ix; tx<=change_radius+ix; tx++, a++)
161      {
162        if (tx>=0 && ty>=0 && tx<=g1_get_map()->width() && ty<=g1_get_map()->height())
163        {
164          i4_3d_vector normal;
165          i4_float tz;
166          w32 old_rgb=v->dynamic_light;
167
168          v->get_normal(normal, tx, ty);
169          tz=v->get_height();
170
171          i4_3d_vector dir=i4_3d_vector(x-tx,
172                                        y-ty,
173                                        h-tz);
174
175          i4_float dist=sqrt(dir.x*dir.x + dir.y*dir.y + dir.z*dir.z);
176          i4_float odist=1.0/dist;
177
178          dir.x*=odist;  // normalize the light direction vector
179          dir.y*=odist;
180          dir.z*=odist;
181
182          i4_float ndl = normal.dot(dir);
183          i4_float atten =  1.0/(c1 + c3*dist*dist);
184
185          if (atten>1) atten=1;
186
187          i4_float intensity=ndl*atten;
188          if (intensity<0) intensity=0;
189
190          sw32 ra,ga,ba, or,og,ob;
191
192          ra=i4_f_to_i(intensity * r * 255);    // calculate how much to add to the current light
193          ga=i4_f_to_i(intensity * g * 255);
194          ba=i4_f_to_i(intensity * b * 255);
195
196          or=(old_rgb>>16)&255;              // grab the old light values
197          og=(old_rgb>>8)&255;
198          ob=(old_rgb)&255;
199     
200          if (ra+or>255) ra=255-or;           // adjust for overflow
201          if (ga+og>255) ga=255-og;
202          if (ba+ob>255) ba=255-ob;
203
204          *a=(ra<<16)|(ga<<8)|ba;           // store the added amount so we can subtract out later
205       
206          v->dynamic_light=((ra+or)<<16) | ((ga+og)<<8) | (ba+ob);
207          v->light_sum|=0x80000000;
208          v++;
209        }
210      }
211    }
212    pf_light_occupy.stop();
213    return i4_T;
214  }
215  else
216  {
217    pf_light_occupy.stop();
218    return i4_F;
219  }
220}
221
222void g1_light_object_class::unoccupy_location()
223{
224  if (!add_intensities)
225    return ;
226
227  pf_light_unoccupy.start();
228  g1_object_class::unoccupy_location();
229
230  sw32 w=change_radius*2+1,h=change_radius*2+1;
231  sw32 ix=i4_f_to_i(x), iy=i4_f_to_i(y);
232  w32 *a=add_intensities;
233
234  for (int ty=-change_radius+iy; ty<=change_radius+iy; ty++)
235  {
236    sw32 start_x=ix-change_radius;
237    if (start_x<0) start_x=0;
238    g1_map_vertex_class *v=g1_get_map()->vertex(start_x,ty);
239    for (int tx=-change_radius+ix; tx<=change_radius+ix; tx++, a++)
240    {
241      if (tx>=0 && ty>=0 && tx<=g1_get_map()->width() && ty<=g1_get_map()->height())     
242      {
243        v->dynamic_light-=*a;
244        v++;
245        v->light_sum=0x80000000;
246      }
247    }
248  }
249 
250  pf_light_unoccupy.stop();
251}
252
Note: See TracBrowser for help on using the repository browser.