00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "texturePeeker.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 TexturePeeker::
00027 TexturePeeker(Texture *tex, Texture::CData *cdata) {
00028 if (cdata->_texture_type == Texture::TT_cube_map) {
00029
00030
00031
00032
00033 return;
00034
00035 } else {
00036
00037
00038
00039 if (tex->do_has_ram_image(cdata) && cdata->_ram_image_compression == Texture::CM_off) {
00040
00041 _image = tex->do_get_ram_image(cdata);
00042 _x_size = cdata->_x_size;
00043 _y_size = cdata->_y_size;
00044 _z_size = cdata->_z_size;
00045 _component_width = cdata->_component_width;
00046 _num_components = cdata->_num_components;
00047 _format = cdata->_format;
00048 _component_type = cdata->_component_type;
00049
00050 } else if (!cdata->_simple_ram_image._image.empty()) {
00051
00052 _image = cdata->_simple_ram_image._image;
00053 _x_size = cdata->_simple_x_size;
00054 _y_size = cdata->_simple_y_size;
00055 _z_size = 1;
00056
00057 _component_width = 1;
00058 _num_components = 4;
00059 _format = Texture::F_rgba;
00060 _component_type = Texture::T_unsigned_byte;
00061
00062 } else {
00063
00064 _image = tex->do_get_uncompressed_ram_image(cdata);
00065 _x_size = cdata->_x_size;
00066 _y_size = cdata->_y_size;
00067 _z_size = cdata->_z_size;
00068 _component_width = cdata->_component_width;
00069 _num_components = cdata->_num_components;
00070 _format = cdata->_format;
00071 _component_type = cdata->_component_type;
00072 }
00073 }
00074
00075 if (_image.is_null()) {
00076 return;
00077 }
00078 _pixel_width = _component_width * _num_components;
00079
00080 switch (_component_type) {
00081 case Texture::T_unsigned_byte:
00082 _get_component = Texture::get_unsigned_byte;
00083 break;
00084
00085 case Texture::T_unsigned_short:
00086 _get_component = Texture::get_unsigned_short;
00087 break;
00088
00089 default:
00090
00091 _image.clear();
00092 return;
00093 }
00094
00095 switch (_format) {
00096 case Texture::F_depth_stencil:
00097 case Texture::F_depth_component:
00098
00099 case Texture::F_red:
00100 _get_texel = get_texel_r;
00101 break;
00102
00103 case Texture::F_green:
00104 _get_texel = get_texel_g;
00105 break;
00106
00107 case Texture::F_blue:
00108 _get_texel = get_texel_b;
00109 break;
00110
00111 case Texture::F_alpha:
00112 _get_texel = get_texel_a;
00113 break;
00114
00115 case Texture::F_luminance:
00116 _get_texel = get_texel_l;
00117 break;
00118
00119 case Texture::F_luminance_alpha:
00120 case Texture::F_luminance_alphamask:
00121 _get_texel = get_texel_la;
00122 break;
00123
00124 case Texture::F_rgb:
00125 case Texture::F_rgb5:
00126 case Texture::F_rgb8:
00127 case Texture::F_rgb12:
00128 case Texture::F_rgb332:
00129 _get_texel = get_texel_rgb;
00130 break;
00131
00132 case Texture::F_rgba:
00133 case Texture::F_rgbm:
00134 case Texture::F_rgba4:
00135 case Texture::F_rgba5:
00136 case Texture::F_rgba8:
00137 case Texture::F_rgba12:
00138 case Texture::F_rgba16:
00139 case Texture::F_rgba32:
00140 _get_texel = get_texel_rgba;
00141 break;
00142 default:
00143
00144 _image.clear();
00145 return;
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 void TexturePeeker::
00163 lookup(LColor &color, PN_stdfloat u, PN_stdfloat v) const {
00164 int x = int((u - cfloor(u)) * (PN_stdfloat)_x_size) % _x_size;
00165 int y = int((v - cfloor(v)) * (PN_stdfloat)_y_size) % _y_size;
00166
00167 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size);
00168 const unsigned char *p = _image.p() + (y * _x_size + x) * _pixel_width;
00169
00170 (*_get_texel)(color, p, _get_component);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 void TexturePeeker::
00186 lookup(LColor &color, PN_stdfloat u, PN_stdfloat v, PN_stdfloat w) const {
00187 int x = int((u - cfloor(u)) * (PN_stdfloat)_x_size) % _x_size;
00188 int y = int((v - cfloor(v)) * (PN_stdfloat)_y_size) % _y_size;
00189 int z = int((w - cfloor(w)) * (PN_stdfloat)_z_size) % _z_size;
00190
00191 nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size &&
00192 z >= 0 && z < _z_size);
00193 const unsigned char *p = _image.p() + (z * _x_size * _y_size + y * _x_size + x) * _pixel_width;
00194
00195 (*_get_texel)(color, p, _get_component);
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 void TexturePeeker::
00210 filter_rect(LColor &color,
00211 PN_stdfloat min_u, PN_stdfloat min_v, PN_stdfloat max_u, PN_stdfloat max_v) const {
00212 int min_x, max_x;
00213 init_rect_minmax(min_x, max_x, min_u, max_u, _x_size);
00214
00215 int min_y, max_y;
00216 init_rect_minmax(min_y, max_y, min_v, max_v, _y_size);
00217
00218 color.set(0.0f, 0.0f, 0.0f, 0.0f);
00219 PN_stdfloat net = 0.0f;
00220 accum_filter_y(color, net, 0,
00221 min_x, max_x, min_u, max_u,
00222 min_y, max_y, min_v, max_v,
00223 1.0f);
00224
00225 if (net != 0.0f) {
00226 color /= net;
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 void TexturePeeker::
00242 filter_rect(LColor &color,
00243 PN_stdfloat min_u, PN_stdfloat min_v, PN_stdfloat min_w,
00244 PN_stdfloat max_u, PN_stdfloat max_v, PN_stdfloat max_w) const {
00245 int min_x, max_x;
00246 init_rect_minmax(min_x, max_x, min_u, max_u, _x_size);
00247
00248 int min_y, max_y;
00249 init_rect_minmax(min_y, max_y, min_v, max_v, _y_size);
00250
00251 int min_z, max_z;
00252 init_rect_minmax(min_z, max_z, min_w, max_w, _z_size);
00253
00254 color.set(0.0f, 0.0f, 0.0f, 0.0f);
00255 PN_stdfloat net = 0.0f;
00256 accum_filter_z(color, net,
00257 min_x, max_x, min_u, max_u,
00258 min_y, max_y, min_v, max_v,
00259 min_z, max_z, min_w, max_w);
00260
00261 if (net != 0.0f) {
00262 color /= net;
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271
00272 void TexturePeeker::
00273 init_rect_minmax(int &min_x, int &max_x, PN_stdfloat &min_u, PN_stdfloat &max_u,
00274 int x_size) {
00275 if (min_u > max_u) {
00276 PN_stdfloat t = min_u;
00277 min_u = max_u;
00278 max_u = t;
00279 }
00280 if (max_u - min_u >= 1.0f) {
00281 min_u = 0.0f;
00282 max_u = 1.0f;
00283 }
00284 min_x = (int)cfloor(min_u * (PN_stdfloat)x_size);
00285 max_x = (int)cceil(max_u * (PN_stdfloat)x_size);
00286 nassertv(min_x <= max_x);
00287 }
00288
00289
00290
00291
00292
00293
00294 void TexturePeeker::
00295 accum_filter_z(LColor &color, PN_stdfloat &net,
00296 int min_x, int max_x, PN_stdfloat min_u, PN_stdfloat max_u,
00297 int min_y, int max_y, PN_stdfloat min_v, PN_stdfloat max_v,
00298 int min_z, int max_z, PN_stdfloat min_w, PN_stdfloat max_w) const {
00299 nassertv(min_z >= 0 && min_z <= _z_size &&
00300 max_z >= 0 && max_z <= _z_size);
00301 int zi = min_z;
00302
00303 if (min_z >= max_z - 1) {
00304
00305 accum_filter_y(color, net, zi % _z_size,
00306 min_x, max_x, min_u, max_u,
00307 min_y, max_y, min_v, max_v,
00308 1.0f);
00309
00310 } else {
00311
00312 PN_stdfloat w = (min_z + 1) - min_w * _z_size;
00313 accum_filter_y(color, net, zi % _z_size,
00314 min_x, max_x, min_u, max_u,
00315 min_y, max_y, min_v, max_v,
00316 w);
00317 int zs = max_z - 1;
00318
00319
00320 zi = min_z + 1;
00321 while (zi < zs) {
00322 accum_filter_y(color, net, zi % _z_size,
00323 min_x, max_x, min_u, max_u,
00324 min_y, max_y, min_v, max_v,
00325 1.0f);
00326 ++zi;
00327 }
00328
00329
00330 w = max_w * _z_size - (max_z - 1);
00331 accum_filter_y(color, net, zi % _z_size,
00332 min_x, max_x, min_u, max_u,
00333 min_y, max_y, min_v, max_v,
00334 w);
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343 void TexturePeeker::
00344 accum_filter_y(LColor &color, PN_stdfloat &net, int zi,
00345 int min_x, int max_x, PN_stdfloat min_u, PN_stdfloat max_u,
00346 int min_y, int max_y, PN_stdfloat min_v, PN_stdfloat max_v,
00347 PN_stdfloat weight) const {
00348 nassertv(zi >= 0 && zi < _z_size);
00349 nassertv(min_y >= 0 && min_y <= _y_size &&
00350 max_y >= 0 && max_y <= _y_size);
00351 int yi = min_y;
00352
00353 if (min_y >= max_y - 1) {
00354
00355 accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight);
00356
00357 } else {
00358
00359 PN_stdfloat w = (min_y + 1) - min_v * _y_size;
00360 accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w);
00361 int ys = max_y - 1;
00362
00363
00364 yi = min_y + 1;
00365 while (yi < ys) {
00366 accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight);
00367 ++yi;
00368 }
00369
00370
00371 w = max_v * _y_size - (max_y - 1);
00372 accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w);
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381 void TexturePeeker::
00382 accum_filter_x(LColor &color, PN_stdfloat &net, int yi, int zi,
00383 int min_x, int max_x, PN_stdfloat min_u, PN_stdfloat max_u,
00384 PN_stdfloat weight) const {
00385 nassertv(yi >= 0 && yi < _y_size && zi >= 0 && zi < _z_size);
00386 nassertv(min_x >= 0 && min_x <= _x_size &&
00387 max_x >= 0 && max_x <= _x_size);
00388
00389
00390 int xi = min_x % _x_size;
00391 const unsigned char *p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
00392
00393 if (min_x >= max_x - 1) {
00394
00395 accum_texel(color, net, p, weight);
00396
00397 } else {
00398
00399 PN_stdfloat w = (min_x + 1) - min_u * _x_size;
00400 accum_texel(color, net, p, weight * w);
00401 int xs = max_x - 1;
00402
00403
00404 xi = min_x + 1;
00405 while (xi < xs) {
00406 if (xi == _x_size) {
00407 xi = 0;
00408 p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
00409 xs -= _x_size;
00410 }
00411 accum_texel(color, net, p, weight);
00412 ++xi;
00413 }
00414
00415
00416 if (xi == _x_size) {
00417 xi = 0;
00418 p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
00419 }
00420 w = max_u * _x_size - (max_x - 1);
00421 accum_texel(color, net, p, weight * w);
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 void TexturePeeker::
00432 accum_texel(LColor &color, PN_stdfloat &net, const unsigned char *&p, PN_stdfloat weight) const {
00433 LColor c;
00434 (*_get_texel)(c, p, _get_component);
00435 color += c * weight;
00436 net += weight;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 void TexturePeeker::
00446 get_texel_r(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00447 color[0] = (*get_component)(p);
00448 color[1] = 0.0f;
00449 color[2] = 0.0f;
00450 color[3] = 1.0f;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 void TexturePeeker::
00460 get_texel_g(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00461 color[0] = 0.0f;
00462 color[1] = (*get_component)(p);
00463 color[2] = 0.0f;
00464 color[3] = 1.0f;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 void TexturePeeker::
00474 get_texel_b(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00475 color[0] = 0.0f;
00476 color[1] = 0.0f;
00477 color[2] = (*get_component)(p);
00478 color[3] = 1.0f;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void TexturePeeker::
00488 get_texel_a(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00489 color[0] = 0.0f;
00490 color[1] = 0.0f;
00491 color[2] = 1.0f;
00492 color[3] = (*get_component)(p);
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 void TexturePeeker::
00502 get_texel_l(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00503 color[0] = (*get_component)(p);
00504 color[1] = color[0];
00505 color[2] = color[0];
00506 color[3] = 1.0f;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 void TexturePeeker::
00516 get_texel_la(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00517 color[0] = (*get_component)(p);
00518 color[1] = color[0];
00519 color[2] = color[0];
00520 color[3] = (*get_component)(p);
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 void TexturePeeker::
00530 get_texel_rgb(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00531 color[2] = (*get_component)(p);
00532 color[1] = (*get_component)(p);
00533 color[0] = (*get_component)(p);
00534 color[3] = 1.0f;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 void TexturePeeker::
00544 get_texel_rgba(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
00545 color[2] = (*get_component)(p);
00546 color[1] = (*get_component)(p);
00547 color[0] = (*get_component)(p);
00548 color[3] = (*get_component)(p);
00549 }