00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00031 rgbaf bg_pixel;
00032 float inverse_alpha, final_r, final_g, final_b, bg_r, bg_b, bg_g;
00033
00034
00036
00037
00038 assert (y<dest.apparent_ht);
00039 assert (x<dest.apparent_wt);
00040
00041 assert(pixel.r <= 255.0f);
00042 assert(pixel.g <= 255.0f);
00043 assert(pixel.b <= 255.0f);
00044
00045 if (pixel.a < 0.0000000001f )
00046 {}
00047 else if (pixel.a > 0.999999999f ){
00048 dest.set_pixel( x, y , pixel);
00049 }
00050 else{
00051 bg_pixel = dest.get_pixel( x, y);
00052
00053
00054
00055
00056
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
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
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
00099
00100
00101 assert(scaling > 0.0f);
00102
00103
00104
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
00112
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
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;
00151 old_ht_div_new_ht = (float)src.surf->h / new_ht;
00152
00153
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
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
00198
00199 first_surf = surfs.front();
00200
00201
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
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
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
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
00278 int x, y;
00279 rgbaf pixel;
00280
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
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
00312
00313
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
00330
00331
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
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 )const
00364 {
00365
00366 int src_x, src_y;
00367 int dst_x, dst_y;
00368 rgbaf pix;
00369 Uint32* ptr;
00370
00371
00372
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 <= 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 <= this->apparent_ht);
00386
00387
00388 SDL_LockSurface(screen);
00389
00390
00391
00392
00393
00394
00395
00396
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