Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

time-critical-procs.cc

Go to the documentation of this file.
00001 // Copyright 2004, 2005 Maurizio Colucci.
00002 //
00003 // This file is part of FACK. 
00004 // 
00005 // FACK is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // FACK is distributed in the hope that it will be useful, but WITHOUT
00011 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00012 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
00013 // License for more details. 
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Foobar; if not, write to the Free Software Foundation,
00017 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018 
00019 #include "fack.hpp" 
00020 
00021 
00022 
00023 void
00024 write_pixel_with_src_alpha( 
00025     cfsurf & dest 
00026     , int x
00027     , int y
00028     , rgbaf pixel)
00029 {
00030     // BEGIN decl
00031     rgbaf bg_pixel;
00032     float inverse_alpha,  final_r, final_g, final_b, bg_r, bg_b, bg_g;
00033     // END
00034 
00036 
00037     // BEGIN precond
00038     assert (y<dest.apparent_ht);
00039     assert (x<dest.apparent_wt);
00040     //assert(pixel.a <= 1.0f); // \todo assert fails sometimes, probably due to numerical problems
00041     assert(pixel.r <= 255.0f);
00042     assert(pixel.g <= 255.0f);
00043     assert(pixel.b <= 255.0f);
00044     // END
00045     if (pixel.a < 0.0000000001f /* completely transparent */)
00046     {}
00047     else if (pixel.a > 0.999999999f /* opaque */){
00048         dest.set_pixel(  x,  y , pixel);
00049     }
00050     else{
00051         bg_pixel = dest.get_pixel( x, y);
00052         //assert(bg_pixel.a == 255.0f);
00053         //assert(pixel.a <= 1.0f);
00054         //alpha = pixel.a / 255.0f; // @@ optimization: remove this
00055         // division: make layers keep alpha
00056         // values already scaled.
00057         inverse_alpha = 1.0f - pixel.a;
00058         bg_r = bg_pixel.r;
00059         bg_g = bg_pixel.g;
00060         bg_b = bg_pixel.b;
00061 
00062         // @@ optimize by taking a rgbaf as input 
00063         final_r = inverse_alpha *  bg_r + pixel.a * pixel.r;
00064         final_g = inverse_alpha *  bg_g + pixel.a * pixel.g;
00065         final_b = inverse_alpha *  bg_b + pixel.a * pixel.b;
00066 
00067         dest.set_pixel(  x,  y , rgbaf( final_r, final_g, final_b, 1.0f));
00068 
00069     }
00070 }
00071 
00072 
00079 void 
00080 blit_char( 
00082     const anim_frame_and_pos & src,
00085     float scaling ,
00087     float lighting,
00089     cfsurf & screen )
00090 {
00091     // BEGIN decl
00092     int new_wt, new_ht;
00093     float old_wt_div_new_wt, old_ht_div_new_ht;
00094     int x, y; 
00095     int hot_x_scaled, hot_y_scaled, x_final_offset, y_final_offset;
00096     float srcx, srcy;
00097     rgbaf pixel; int destx, desty;
00098     // END
00099 
00100     // BEGIN precond
00101     assert(scaling > 0.0f);
00102     //     assert(screen.apparent_wt == screen.real_wt); // @@ why does this fail?
00103     //     assert(screen.apparent_ht == screen.real_ht);
00104     // END
00105 
00106     new_wt = int(float( src.surf->w) * scaling);
00107     new_ht = int(float( src.surf->h) * scaling);
00108 
00109     if (new_ht == src.surf->h || new_wt == src.surf->w)
00110     {
00111         // use different algo to prevent fuzzy image. It is also
00112         // faster.
00113 
00114         new_ht = src.surf->h;
00115         new_wt = src.surf->w;
00116             
00117         hot_x_scaled  = src.surf->hot_spot.x;
00118         hot_y_scaled  = src.surf->hot_spot.y;
00119 
00120         x_final_offset = src.position_x - hot_x_scaled;
00121         y_final_offset = src.position_y - hot_y_scaled;
00122 
00123         // @@ Optimization: move the clipping condition out of the loop.
00124         for (x = 0 ; x< new_wt; x++)
00125         {
00126             for (y = 0 ; y< new_ht ; y++)
00127             {
00128                 pixel = mul_scalar_rgbaf_noalpha(lighting, src.surf->get_pixel( x, y));
00129                 destx = x + x_final_offset;
00130                 desty = y + y_final_offset;
00131 
00132                 if (  destx >= screen.offs_x && destx < screen.offs_x + screen.real_wt
00133                       && 
00134                       desty>=screen.offs_y && desty < screen.offs_y + screen.real_ht)
00135                 {
00136                     write_pixel_with_src_alpha(screen, destx, desty , pixel);
00137                 }
00138             }
00139         }
00140 
00141     }
00142     else
00143     {
00144         hot_x_scaled  = int(float(src.surf->hot_spot.x) * scaling);
00145         hot_y_scaled  = int(float(src.surf->hot_spot.y) * scaling);
00146 
00147         x_final_offset = src.position_x - hot_x_scaled;
00148         y_final_offset = src.position_y - hot_y_scaled;
00149 
00150         old_wt_div_new_wt = (float)src.surf->w / new_wt; // @@ dangerous if they are very close?
00151         old_ht_div_new_ht = (float)src.surf->h / new_ht;
00152 
00153         // @@ Optimization: move the clipping condition out of the loop.
00154         for (x = 0 ; x< new_wt; x++)
00155         {
00156             for (y = 0 ; y< new_ht ; y++)
00157             {
00158                 srcx = float(x) * old_wt_div_new_wt;
00159                 srcy = float(y) * old_ht_div_new_ht;
00160                         
00161                 pixel = mul_scalar_rgbaf_noalpha(lighting, 
00162                                                  src.surf->get_pixel_with_interpolation( srcx, srcy));
00163                 destx = x + x_final_offset;
00164                 desty = y + y_final_offset;
00165 
00166                 if (  destx >= screen.offs_x && destx < screen.offs_x + screen.real_wt
00167                       && 
00168                       desty>=screen.offs_y && desty < screen.offs_y + screen.real_ht)
00169                 {
00170                     write_pixel_with_src_alpha(screen, destx, desty , pixel);
00171                 }
00172             }
00173         }
00174     }
00175 }
00176 
00179 inline
00180 pt<cfsurf> 
00181 sum_each_pixel( 
00182     const list<surf_and_weight > & surfs, 
00183     float time,
00184     SDL_Rect visible_rect)
00185 {
00186     //BEGIN decl.
00187     rgbaf dest_color;
00188     pt<cfsurf> merged_surf;
00189     int  wt, ht, x, y, offs_x, offs_y, max_x, max_y;
00190     surf_and_weight first_surf;
00191     list<surf_and_weight > ::const_iterator l;
00192     float a;
00193     double cosine;
00194     map<surf_and_weight, double> oscillation_of;
00195     list<int> offs_xs, offs_ys, max_xs, max_ys;
00196     int left_bound, right_bound, top_bound, bottom_bound;
00197     // END
00198 
00199     first_surf = surfs.front();
00200 
00201     // BEGIN precond
00202     assert(surfs.size() > 0);
00203     foreach(l, surfs){
00204         assert ( l->surf->apparent_wt == first_surf.surf->apparent_wt);
00205         assert ( l->surf->apparent_ht == first_surf.surf->apparent_ht);
00206     }
00207     // END
00208 
00209     setof_( l->surf->offs_x, l, surfs, true, offs_xs);
00210     setof_( l->surf->offs_y, l, surfs, true, offs_ys);
00211 
00212     offs_x = min(offs_xs);
00213     offs_y = min(offs_ys);
00214 
00215     setof_( l->surf->offs_x + l->surf->real_wt, l, surfs, true, max_xs);
00216     setof_( l->surf->offs_y + l->surf->real_ht, l, surfs, true, max_ys);
00217 
00218     max_x = max(max_xs);
00219     max_y = max(max_ys);
00220 
00221     wt = max_x - offs_x;
00222     ht = max_y - offs_y;
00223 
00224     merged_surf = NEW( cfsurf(first_surf.surf->apparent_wt
00225                            , first_surf.surf->apparent_ht
00226                            , wt
00227                            , ht
00228                            , offs_x
00229                            , offs_y));
00230 
00231 
00232     // BEGIN fill the map "oscillation_of"
00233     foreach(l, surfs){
00234         a = l->oscillation_amplitude;
00235         assert (0.0f <= a && a< 0.5f);
00236         cosine = cos(l->oscillation_speed * time); 
00237         oscillation_of[*l] =  a  * pow(cosine,3) + 1.0f - a ; 
00238     }
00239     // END
00240 
00241 
00242     left_bound = std::max(offs_x, int(visible_rect.x));
00243     top_bound = std::max(offs_y, int(visible_rect.y));
00244     bottom_bound = std::min(offs_y + ht, int(visible_rect.y + visible_rect.h));
00245     right_bound = std::min(offs_x + wt, int(visible_rect.x + visible_rect.w));
00246 
00247     for ( x = left_bound; x < right_bound; x++)
00248     {
00249         for ( y = top_bound; y < bottom_bound; y++)
00250         {
00251             dest_color = rgbaf(0,0,0,0);
00252 
00253             foreach(l, surfs){  
00254 
00255                 dest_color = sum_rgbaf ( 
00256                     dest_color ,
00257                     mul_scalar_rgbaf(
00258                         l->calc_weight(int_pair(x, y)),
00259                         mul_scalar_rgbaf_noalpha(
00260                             map_get(oscillation_of, *l),
00261                             l->surf->get_pixel( x, y))));
00262             }
00263             merged_surf->set_pixel( x, y, dest_color);
00264         }
00265     } 
00266     return merged_surf;
00267 }
00268         
00269 
00270 
00271 
00272 
00273 void
00274 cfsurf::blit_with_src_alpha(
00275     cfsurf & dest)const
00276 {
00277     // BEGIN decl.
00278     int x, y;
00279     rgbaf pixel;
00280     // END
00281 
00282     assert(apparent_ht == dest.apparent_ht);
00283     assert(apparent_wt == dest.apparent_wt);
00284 
00285     for(x = offs_x ; x< offs_x + real_wt ; x++){
00286         for(y = offs_y ; y< offs_y + real_ht ; y++){
00287             pixel = this->get_pixel( x, y);
00288             write_pixel_with_src_alpha(dest, x, y, pixel);
00289         }
00290     }
00291 }
00292 
00293 
00294 
00295 pt<layer_lit> 
00296 FACK::lit_layer_of_unlit_layer ( 
00297     const layer_unlit_after_anim & unlit,
00298     const set<pt<light> > & on_lights,
00299     float time,
00300     SDL_Rect visible_rect)const
00301 {
00302     // BEGIN decl.
00303     float sum;
00304     set<pt<light> >::const_iterator l;
00305     map<pt<light>, float> normalized_weight_of_light;
00306     list<layer_unlit_after_anim >::const_iterator obj_unlit;
00307     pt<cfsurf> surf;
00308     list<surf_and_weight > on_surfs;
00309     list<surf_with_name>::const_iterator v;
00310     bool exists_a_layer_which_represents_that_light;
00311     // END
00312 
00313     // BEGIN precond
00314     assert(on_lights.size() > 0);
00315     assert(unlit.lit_versions.size() >0);
00316     
00317     foreach(l, on_lights){
00318 
00319         exists_a_layer_which_represents_that_light = false;
00320 
00321         foreach(v, unlit.lit_versions){
00322             if(v->ligh == *l )
00323             {
00324                 exists_a_layer_which_represents_that_light = true;
00325             }
00326         }
00327         assert(exists_a_layer_which_represents_that_light);
00328     }
00329     // END
00330 
00331     // BEGIN compute normalized_weight_of_light
00332 
00334     sum = 0.0f;
00335     foreach(l, on_lights){
00336         sum += (*l)->weight;}
00337 
00338     foreach(l, on_lights){
00339         normalized_weight_of_light[*l] = (*l)->weight / sum;}
00340     // END
00341 
00342     setof_ (  surf_and_weight(
00343                   v->surf, 
00344                   map_get(normalized_weight_of_light, v->ligh), 
00345                   v->ligh->oscillation_amplitude, 
00346                   v->ligh->oscillation_speed,
00347                   circle_of_light(v->ligh)), 
00348         v,
00349         unlit.lit_versions,
00350         in(v->ligh, on_lights),
00351         on_surfs);
00352     
00353     assert(on_surfs.size() >0);
00354 
00355     surf = sum_each_pixel( on_surfs, time, visible_rect);
00356     return NEW(layer_lit( surf, unlit.y_walkbehind));
00357 }
00358 
00359 
00360 void
00361 cfsurf::opaque_blit_to_sdl_surface(
00362     SDL_Surface * screen,
00363     SDL_Rect src_rect_to_blit /* this rect will be blitted at 0,0 on the screen */ )const
00364 {
00365     // BEGIN decl
00366     int src_x, src_y;
00367     int dst_x, dst_y;
00368     rgbaf pix;
00369     Uint32* ptr;
00370     // END
00371 
00372     // BEGIN precond
00373     assert(screen->format->BytesPerPixel == 4);
00374 
00375     assert(src_rect_to_blit.x >=0);
00376     assert(src_rect_to_blit.x < this->apparent_wt);
00377 
00378     assert(src_rect_to_blit.x + src_rect_to_blit.w >= 0);
00379     assert(src_rect_to_blit.x + src_rect_to_blit.w <= /* sic*/ this->apparent_wt);
00380 
00381     assert(src_rect_to_blit.y >=0);
00382     assert(src_rect_to_blit.y < this->apparent_ht);
00383 
00384     assert(src_rect_to_blit.y + src_rect_to_blit.h >= 0);
00385     assert(src_rect_to_blit.y + src_rect_to_blit.h <= /*sic */this->apparent_ht);
00386     // END
00387 
00388     SDL_LockSurface(screen);
00389 
00390     // I removed the optimiz:
00391     // 
00392     // for (x = offs_x; x < offs_x + real_wt; x++)
00393     //
00394     // it is useless because this proc is only used to blit the final
00395     // surface to the screen.  Furthermore, with that optimization it
00396     // was silly to call get_pixel, because it has an if inside.
00397 
00398 
00399     for (src_x = src_rect_to_blit.x, dst_x = 0;
00400          src_x < src_rect_to_blit.x + src_rect_to_blit.w; 
00401          src_x++, dst_x ++)
00402     {
00403         for (src_y = src_rect_to_blit.y, dst_y = 0;
00404              src_y < src_rect_to_blit.y + src_rect_to_blit.h;
00405              src_y++, dst_y ++)
00406         {
00407             pix = this->get_pixel( src_x, src_y); 
00410 
00411             ptr = (Uint32 *) (screen->pixels) + dst_x + dst_y * screen->w;
00412 
00413             * ptr = SDL_MapRGB(screen->format
00414                 , Uint8(pix.r)
00415                 , Uint8(pix.g)
00416                 , Uint8(pix.b));
00417         }
00418     }
00419     SDL_UnlockSurface(screen);
00420 }
00421 
00422 
00423 
00424   
00425 
00426 

Generated on Wed May 25 15:36:07 2005 for FACK by  doxygen 1.4.0