00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "vp_global.h"
00032
00033 static int FactorAffineView ANSI_ARGS((vpContext *vpc, vpMatrix4 vm));
00034 static int FactorPerspectiveView ANSI_ARGS((vpContext *vpc, vpMatrix4 vm));
00035 static void ComputeAffineOpacityCorrection ANSI_ARGS((vpContext *vpc,
00036 double shear_i, double shear_j, float table[VP_OPACITY_MAX+1]));
00037 static void CheckRenderBuffers ANSI_ARGS((vpContext *vpc));
00038 static void ComputeLightViewTransform ANSI_ARGS((vpContext *vpc,vpMatrix4 vm));
00039 static int FactorLightView ANSI_ARGS((vpContext *vpc, vpMatrix4 vm));
00040 static void CheckShadowBuffer ANSI_ARGS((vpContext *vpc));
00041
00042
00043
00044
00045
00046
00047
00048 vpResult
00049 VPFactorView(vpc)
00050 vpContext *vpc;
00051 {
00052 vpMatrix4 vm;
00053 int retcode;
00054
00055 if (vpc->factored_view_ready) {
00056 CheckRenderBuffers(vpc);
00057 return(VP_OK);
00058 }
00059
00060
00061 VPComputeViewTransform(vpc, vm);
00062
00063
00064 if (fabs(vm[3][0]) < VP_EPS && fabs(vm[3][1]) < VP_EPS &&
00065 fabs(vm[3][2]) < VP_EPS && fabs(vm[3][3]-1.) < VP_EPS) {
00066 if ((retcode = FactorAffineView(vpc, vm)) != VP_OK)
00067 return(retcode);
00068 ComputeAffineOpacityCorrection(vpc, vpc->shear_i, vpc->shear_j,
00069 vpc->affine_opac_correct);
00070 } else {
00071 FactorPerspectiveView(vpc, vm);
00072 }
00073 CheckRenderBuffers(vpc);
00074
00075
00076
00077 if ((retcode = VPCheckShadows(vpc)) != VP_OK)
00078 return(retcode);
00079 if (vpc->enable_shadows) {
00080 ComputeLightViewTransform(vpc, vm);
00081 if ((retcode = FactorLightView(vpc, vm)) != VP_OK)
00082 return(retcode);
00083 ComputeAffineOpacityCorrection(vpc, vpc->shadow_shear_i,
00084 vpc->shadow_shear_j,
00085 vpc->shadow_opac_correct);
00086 CheckShadowBuffer(vpc);
00087 }
00088 return(VP_OK);
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 void
00098 VPComputeViewTransform(vpc, vm)
00099 vpContext *vpc;
00100 vpMatrix4 vm;
00101 {
00102 vpMatrix4 prematrix;
00103 vpMatrix4 viewportm;
00104 vpMatrix4 tmp1m, tmp2m, tmp3m;
00105 int maxdim;
00106 double scale;
00107
00108
00109 vpIdentity4(prematrix);
00110 maxdim = vpc->xlen;
00111 if (vpc->ylen > maxdim)
00112 maxdim = vpc->ylen;
00113 if (vpc->zlen > maxdim)
00114 maxdim = vpc->zlen;
00115 scale = 1. / (double)maxdim;
00116 prematrix[0][0] = scale;
00117 prematrix[1][1] = scale;
00118 prematrix[2][2] = scale;
00119 prematrix[0][3] = -vpc->xlen * scale * 0.5;
00120 prematrix[1][3] = -vpc->ylen * scale * 0.5;
00121 prematrix[2][3] = -vpc->zlen * scale * 0.5;
00122
00123
00124 vpIdentity4(viewportm);
00125 viewportm[0][0] = 0.5 * vpc->image_width;
00126 viewportm[0][3] = 0.5 * vpc->image_width;
00127 viewportm[1][1] = 0.5 * vpc->image_height;
00128 viewportm[1][3] = 0.5 * vpc->image_height;
00129 viewportm[2][2] = -0.5;
00130 viewportm[2][3] = 0.5;
00131
00132
00133 vpMatrixMult4(tmp1m, vpc->transforms[VP_MODEL], prematrix);
00134 vpMatrixMult4(tmp2m, vpc->transforms[VP_VIEW], tmp1m);
00135 vpMatrixMult4(tmp3m, vpc->transforms[VP_PROJECT], tmp2m);
00136 vpMatrixMult4(vm, viewportm, tmp3m);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static int
00151 FactorAffineView(vpc, vm)
00152 vpContext *vpc;
00153 vpMatrix4 vm;
00154 {
00155 vpMatrix4 p;
00156 vpMatrix4 pvm;
00157 int icount, jcount, kcount;
00158 vpVector4 xobj, yobj, zobj;
00159 vpVector4 xim, yim, zim;
00160 double x, y, z, denom;
00161
00162 Debug((vpc, VPDEBUG_VIEW, "FactorAffineView\n"));
00163
00164 vpc->affine_view = 1;
00165
00166
00167
00168
00169
00170
00171 vpSetVector4(xobj, 1., 0., 0., 0.);
00172 vpSetVector4(yobj, 0., 1., 0., 0.);
00173 vpSetVector4(zobj, 0., 0., 1., 0.);
00174 vpMatrixVectorMult4(xim, vm, xobj);
00175 vpMatrixVectorMult4(yim, vm, yobj);
00176 vpMatrixVectorMult4(zim, vm, zobj);
00177 x = fabs((vpNormalize3(xim) == VPERROR_SINGULAR) ? 0. : xim[2]);
00178 y = fabs((vpNormalize3(yim) == VPERROR_SINGULAR) ? 0. : yim[2]);
00179 z = fabs((vpNormalize3(zim) == VPERROR_SINGULAR) ? 0. : zim[2]);
00180 if (x >= y) {
00181 if (x >= z) {
00182 vpc->best_view_axis = VP_X_AXIS;
00183 } else {
00184 vpc->best_view_axis = VP_Z_AXIS;
00185 }
00186 } else {
00187 if (y >= z) {
00188 vpc->best_view_axis = VP_Y_AXIS;
00189 } else {
00190 vpc->best_view_axis = VP_Z_AXIS;
00191 }
00192 }
00193 switch (vpc->axis_override) {
00194 case VP_X_AXIS:
00195 if (x < VP_EPS)
00196 return(VPSetError(vpc, VPERROR_SINGULAR));
00197 vpc->best_view_axis = VP_X_AXIS;
00198 break;
00199 case VP_Y_AXIS:
00200 if (y < VP_EPS)
00201 return(VPSetError(vpc, VPERROR_SINGULAR));
00202 vpc->best_view_axis = VP_Y_AXIS;
00203 break;
00204 case VP_Z_AXIS:
00205 if (z < VP_EPS)
00206 return(VPSetError(vpc, VPERROR_SINGULAR));
00207 vpc->best_view_axis = VP_Z_AXIS;
00208 break;
00209 default:
00210 break;
00211 }
00212
00213
00214
00215 bzero(p, sizeof(vpMatrix4));
00216 switch (vpc->best_view_axis) {
00217 case VP_X_AXIS:
00218 p[0][2] = 1.;
00219 p[1][0] = 1.;
00220 p[2][1] = 1.;
00221 p[3][3] = 1.;
00222 icount = vpc->ylen;
00223 jcount = vpc->zlen;
00224 kcount = vpc->xlen;
00225 break;
00226 case VP_Y_AXIS:
00227 p[0][1] = 1.;
00228 p[1][2] = 1.;
00229 p[2][0] = 1.;
00230 p[3][3] = 1.;
00231 icount = vpc->zlen;
00232 jcount = vpc->xlen;
00233 kcount = vpc->ylen;
00234 break;
00235 case VP_Z_AXIS:
00236 p[0][0] = 1.;
00237 p[1][1] = 1.;
00238 p[2][2] = 1.;
00239 p[3][3] = 1.;
00240 icount = vpc->xlen;
00241 jcount = vpc->ylen;
00242 kcount = vpc->zlen;
00243 break;
00244 }
00245 vpMatrixMult4(pvm, vm, p);
00246
00247
00248 denom = pvm[0][0]*pvm[1][1] - pvm[0][1]*pvm[1][0];
00249 if (fabs(denom) < VP_EPS)
00250 return(VPSetError(vpc, VPERROR_SINGULAR));
00251 vpc->shear_i = (pvm[0][2]*pvm[1][1] - pvm[0][1]*pvm[1][2]) / denom;
00252 vpc->shear_j = (pvm[0][0]*pvm[1][2] - pvm[1][0]*pvm[0][2]) / denom;
00253 if (pvm[2][0]*vpc->shear_i + pvm[2][1]*vpc->shear_j - pvm[2][2] > 0)
00254 vpc->reverse_slice_order = 0;
00255 else
00256 vpc->reverse_slice_order = 1;
00257
00258
00259 vpc->intermediate_width = icount + 1 + (int)ceil((kcount-1)*
00260 fabs(vpc->shear_i));
00261 vpc->intermediate_height = jcount + 1 + (int)ceil((kcount-1)*
00262 fabs(vpc->shear_j));
00263
00264
00265 if (vpc->shear_i >= 0.)
00266 vpc->trans_i = 1.;
00267 else
00268 vpc->trans_i = 1. - vpc->shear_i * (kcount - 1);
00269 if (vpc->shear_j >= 0.)
00270 vpc->trans_j = 1.;
00271 else
00272 vpc->trans_j = 1. - vpc->shear_j * (kcount - 1);
00273
00274
00275 vpc->depth_di = pvm[2][0];
00276 vpc->depth_dj = pvm[2][1];
00277 vpc->depth_dk = pvm[2][2];
00278 vpc->depth_000 = pvm[2][3];
00279
00280
00281 vpc->warp_2d[0][0] = pvm[0][0];
00282 vpc->warp_2d[0][1] = pvm[0][1];
00283 vpc->warp_2d[0][2] = pvm[0][3] - pvm[0][0]*vpc->trans_i -
00284 pvm[0][1]*vpc->trans_j;
00285 vpc->warp_2d[1][0] = pvm[1][0];
00286 vpc->warp_2d[1][1] = pvm[1][1];
00287 vpc->warp_2d[1][2] = pvm[1][3] - pvm[1][0]*vpc->trans_i -
00288 pvm[1][1]*vpc->trans_j;
00289 vpc->warp_2d[2][0] = 0.;
00290 vpc->warp_2d[2][1] = 0.;
00291 vpc->warp_2d[2][2] = 1.;
00292
00293 vpc->factored_view_ready = 1;
00294
00295 Debug((vpc, VPDEBUG_VIEW, " best_view_axis: %c%c\n",
00296 vpc->reverse_slice_order ? '-' : '+',
00297 vpc->best_view_axis == VP_X_AXIS ? 'x' :
00298 (vpc->best_view_axis == VP_Y_AXIS ? 'y' : 'z')));
00299 Debug((vpc, VPDEBUG_VIEW, " shear factors: %g %g\n",
00300 vpc->shear_i, vpc->shear_j));
00301 Debug((vpc, VPDEBUG_VIEW, " translation: %g %g\n",
00302 vpc->trans_i, vpc->trans_j));
00303 Debug((vpc, VPDEBUG_VIEW, " depth: d000: %g\n", vpc->depth_000));
00304 Debug((vpc, VPDEBUG_VIEW, " di: %g\n", vpc->depth_di));
00305 Debug((vpc, VPDEBUG_VIEW, " dj: %g\n", vpc->depth_dj));
00306 Debug((vpc, VPDEBUG_VIEW, " dk: %g\n", vpc->depth_dk));
00307 Debug((vpc, VPDEBUG_VIEW, " intermediate image size: %d %d\n",
00308 vpc->intermediate_width, vpc->intermediate_height));
00309 return(VP_OK);
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static int
00323 FactorPerspectiveView(vpc, vm)
00324 vpContext *vpc;
00325 vpMatrix4 vm;
00326 {
00327 vpc->affine_view = 0;
00328 return(VP_OK);
00329
00330 #ifdef notdef
00331 Matrix4 p;
00332 Matrix4 pvm;
00333 Matrix4 m2d;
00334 Matrix4 t;
00335 double alpha1, alpha2, alpha3, alpha4;
00336 int icount, jcount, kcount;
00337 Vector4 xobj, yobj, zobj;
00338 double x, y, z, denom;
00339 double i0, j0, i1, j1;
00340 double imin, imax, jmin, jmax;
00341
00342 Debug((DEBUG_VIEW, "FactorPerspectiveView\n"));
00343
00344 rbuf->perspective_proj = 1;
00345
00346
00347
00348
00349
00350
00351 xobj[0] = 1.; xobj[1] = 0.; xobj[2] = 0.; xobj[3] = 0.;
00352 yobj[0] = 0.; yobj[1] = 1.; yobj[2] = 0.; yobj[3] = 0.;
00353 zobj[0] = 0.; zobj[1] = 0.; zobj[2] = 1.; zobj[3] = 0.;
00354 TransformVector4(xobj, view->view_matrix);
00355 TransformVector4(yobj, view->view_matrix);
00356 TransformVector4(zobj, view->view_matrix);
00357
00358
00359 xobj[2] = fabs(xobj[2]);
00360 yobj[2] = fabs(yobj[2]);
00361 zobj[2] = fabs(zobj[2]);
00362 x = (xobj[2] < EPS) ? 0. :
00363 (xobj[2] / sqrt(xobj[0]*xobj[0] + xobj[1]*xobj[1] + xobj[2]*xobj[2]));
00364 y = (yobj[2] < EPS) ? 0. :
00365 (yobj[2] / sqrt(yobj[0]*yobj[0] + yobj[1]*yobj[1] + yobj[2]*yobj[2]));
00366 z = (zobj[2] < EPS) ? 0. :
00367 (zobj[2] / sqrt(zobj[0]*zobj[0] + zobj[1]*zobj[1] + zobj[2]*zobj[2]));
00368 if (x >= y) {
00369 if (x >= z) {
00370 rbuf->best_view_axis = VP_XAXIS;
00371 } else {
00372 rbuf->best_view_axis = VP_ZAXIS;
00373 }
00374 } else {
00375 if (y >= z) {
00376 rbuf->best_view_axis = VP_YAXIS;
00377 } else {
00378 rbuf->best_view_axis = VP_ZAXIS;
00379 }
00380 }
00381
00382
00383
00384 bzero(p, sizeof(Matrix4));
00385 switch (rbuf->best_view_axis) {
00386 case VP_XAXIS:
00387 p[0][2] = 1.;
00388 p[1][0] = 1.;
00389 p[2][1] = 1.;
00390 p[3][3] = 1.;
00391 icount = ylen;
00392 jcount = zlen;
00393 kcount = xlen;
00394 break;
00395 case VP_YAXIS:
00396 p[0][1] = 1.;
00397 p[1][2] = 1.;
00398 p[2][0] = 1.;
00399 p[3][3] = 1.;
00400 icount = zlen;
00401 jcount = xlen;
00402 kcount = ylen;
00403 break;
00404 case VP_ZAXIS:
00405 p[0][0] = 1.;
00406 p[1][1] = 1.;
00407 p[2][2] = 1.;
00408 p[3][3] = 1.;
00409 icount = xlen;
00410 jcount = ylen;
00411 kcount = zlen;
00412 break;
00413 default:
00414 VPBug("wierd value for best_view_axis in FactorPerspectiveView\n");
00415 }
00416 MatrixMult4(pvm, view->view_matrix, p);
00417
00418
00419 alpha1 = pvm[3][1] * (pvm[0][3]*pvm[1][2] - pvm[0][2]*pvm[1][3]) +
00420 pvm[3][2] * (pvm[0][1]*pvm[1][3] - pvm[0][3]*pvm[1][1]) +
00421 pvm[3][3] * (pvm[0][2]*pvm[1][1] - pvm[0][1]*pvm[1][2]);
00422 alpha2 = pvm[3][0] * (pvm[0][2]*pvm[1][3] - pvm[0][3]*pvm[1][2]) +
00423 pvm[3][2] * (pvm[0][3]*pvm[1][0] - pvm[0][0]*pvm[1][3]) +
00424 pvm[3][3] * (pvm[0][0]*pvm[1][2] - pvm[0][2]*pvm[1][0]);
00425 alpha3 = pvm[3][0] * (pvm[0][1]*pvm[1][2] - pvm[0][2]*pvm[1][1]) +
00426 pvm[3][1] * (pvm[0][2]*pvm[1][0] - pvm[0][0]*pvm[1][2]) +
00427 pvm[3][2] * (pvm[0][0]*pvm[1][1] - pvm[0][1]*pvm[1][0]);
00428 alpha4 = pvm[3][0] * (pvm[0][1]*pvm[1][3] - pvm[0][3]*pvm[1][1]) +
00429 pvm[3][1] * (pvm[0][3]*pvm[1][0] - pvm[0][0]*pvm[1][3]) +
00430 pvm[3][3] * (pvm[0][0]*pvm[1][1] - pvm[0][1]*pvm[1][0]);
00431
00432
00433 if (pvm[2][2] - (pvm[2][0]*alpha1 + pvm[2][1]*alpha2)/(alpha3+alpha4) > 0)
00434 rbuf->reverse_k_order = 1;
00435 else
00436 rbuf->reverse_k_order = 0;
00437
00438
00439 rbuf->w_factor = alpha3 / alpha4;
00440 if (rbuf->reverse_k_order)
00441 rbuf->normalize_scale = 1. + rbuf->w_factor*(kcount-1);
00442 else
00443 rbuf->normalize_scale = 1.;
00444
00445
00446 denom = 1. / (alpha4 + alpha3*(kcount-1));
00447 i0 = rbuf->normalize_scale*alpha1*(kcount-1) * denom;
00448 j0 = rbuf->normalize_scale*alpha2*(kcount-1) * denom;
00449 i1 = rbuf->normalize_scale*(alpha4*icount + alpha1*(kcount-1)) * denom;
00450 j1 = rbuf->normalize_scale*(alpha4*jcount + alpha2*(kcount-1)) * denom;
00451 imin = MIN(0, i0);
00452 imax = MAX(rbuf->normalize_scale*icount, i1);
00453 jmin = MIN(0, j0);
00454 jmax = MAX(rbuf->normalize_scale*jcount, j1);
00455
00456
00457 rbuf->intermediate_width = (int)ceil(imax - imin);
00458 rbuf->intermediate_height = (int)ceil(jmax - jmin);
00459
00460
00461 rbuf->shear_i = (rbuf->normalize_scale*alpha1 - alpha3*imin) / alpha4;
00462 rbuf->shear_j = (rbuf->normalize_scale*alpha2 - alpha3*jmin) / alpha4;
00463 rbuf->trans_i = -imin;
00464 rbuf->trans_j = -jmin;
00465
00466
00467 rbuf->depth_di = pvm[2][0];
00468 rbuf->depth_dj = pvm[2][1];
00469 rbuf->depth_dk = pvm[2][2];
00470 rbuf->depth_000 = pvm[2][3];
00471 rbuf->w_di = pvm[3][0];
00472 rbuf->w_dj = pvm[3][1];
00473 rbuf->w_dk = pvm[3][2];
00474 rbuf->w_000 = pvm[3][3];
00475
00476
00477 Identity4(t);
00478 t[0][0] = 1. / rbuf->normalize_scale;
00479 t[1][1] = 1. / rbuf->normalize_scale;
00480 t[0][2] = -alpha1 / alpha4;
00481 t[1][2] = -alpha2 / alpha4;
00482 t[3][2] = -alpha3 / alpha4;
00483 t[0][3] = imin / rbuf->normalize_scale;
00484 t[1][3] = jmin / rbuf->normalize_scale;
00485 MatrixMult4(m2d, pvm, t);
00486
00487 rbuf->warp_2d[0][0] = m2d[0][0];
00488 rbuf->warp_2d[1][0] = m2d[1][0];
00489 rbuf->warp_2d[2][0] = m2d[3][0];
00490 rbuf->warp_2d[0][1] = m2d[0][1];
00491 rbuf->warp_2d[1][1] = m2d[1][1];
00492 rbuf->warp_2d[2][1] = m2d[3][1];
00493 rbuf->warp_2d[0][2] = m2d[0][3];
00494 rbuf->warp_2d[1][2] = m2d[1][3];
00495 rbuf->warp_2d[2][2] = m2d[3][3];
00496 #endif
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 static void
00508 ComputeAffineOpacityCorrection(vpc, shear_i, shear_j, table)
00509 vpContext *vpc;
00510 double shear_i;
00511 double shear_j;
00512 float table[VP_OPACITY_MAX+1];
00513 {
00514 float voxel_size;
00515 int i;
00516
00517 Debug((vpc, VPDEBUG_OPCCORRECT,
00518 "Computing affine opacity correction table.\n"));
00519 voxel_size = sqrt(1 + shear_i*shear_i + shear_j*shear_j);
00520 for (i = 0; i <= VP_OPACITY_MAX; i++) {
00521 #ifdef NO_OPAC_CORRECT
00522 table[i] = (double)i / (double)VP_OPACITY_MAX;
00523 #else
00524 table[i] = 1.-pow(1.-(double)i/(double)VP_OPACITY_MAX,voxel_size);
00525 #endif
00526 }
00527 }
00528
00529
00530
00531
00532
00533
00534
00535 static void
00536 CheckRenderBuffers(vpc)
00537 vpContext *vpc;
00538 {
00539 int new_max_width, new_max_height, new_max_scan;
00540 int resize = 0;
00541
00542
00543 if (vpc->intermediate_width > vpc->max_intermediate_width) {
00544 new_max_width = MAX(vpc->intermediate_width,
00545 vpc->int_image_width_hint);
00546 resize = 1;
00547 } else {
00548 new_max_width = MAX(vpc->max_intermediate_width,
00549 vpc->int_image_width_hint);
00550 }
00551 if (vpc->intermediate_height > vpc->max_intermediate_height) {
00552 new_max_height = MAX(vpc->intermediate_height,
00553 vpc->int_image_height_hint);
00554 resize = 1;
00555 } else {
00556 new_max_height = MAX(vpc->max_intermediate_height,
00557 vpc->int_image_height_hint);
00558 }
00559 new_max_scan = vpc->xlen;
00560 if (vpc->ylen > new_max_scan)
00561 new_max_scan = vpc->ylen;
00562 if (vpc->zlen > new_max_scan)
00563 new_max_scan = vpc->zlen;
00564 if (new_max_scan > vpc->max_scan_length)
00565 resize = 1;
00566 if (vpc->color_channels != vpc->intermediate_color_channels)
00567 resize = 1;
00568
00569
00570 if (resize)
00571 VPResizeRenderBuffers(vpc, new_max_width, new_max_height,new_max_scan);
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 void
00581 VPResizeRenderBuffers(vpc, max_width, max_height, max_scan)
00582 vpContext *vpc;
00583 int max_width;
00584 int max_height;
00585 int max_scan;
00586 {
00587
00588 if (vpc->int_image.gray_intim != NULL) {
00589 Debug((vpc, VPDEBUG_RBUF, "Freeing old RenderBuffer(%d,%d,%d,%d)\n",
00590 vpc->max_intermediate_width, vpc->max_intermediate_height,
00591 vpc->max_scan_length, vpc->intermediate_color_channels));
00592 Dealloc(vpc, vpc->int_image.gray_intim);
00593 }
00594
00595
00596 Debug((vpc, VPDEBUG_RBUF, "Allocating RenderBuffer(%d,%d,%d,%d)\n",
00597 max_width, max_height, max_scan, vpc->color_channels));
00598 vpc->max_intermediate_width = max_width;
00599 vpc->max_intermediate_height = max_height;
00600 vpc->max_scan_length = max_scan;
00601 vpc->intermediate_color_channels = vpc->color_channels;
00602 if (max_width > 0) {
00603 if (vpc->color_channels == 1) {
00604 Alloc(vpc, vpc->int_image.gray_intim, GrayIntPixel *,
00605 max_width * max_height * sizeof(GrayIntPixel), "int_image");
00606 } else {
00607 Alloc(vpc, vpc->int_image.rgb_intim, RGBIntPixel *,
00608 max_width * max_height * sizeof(RGBIntPixel), "int_image");
00609 }
00610 } else {
00611 vpc->int_image.gray_intim = NULL;
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 void
00622 VPResizeDepthCueTable(vpc, entries, copy)
00623 vpContext *vpc;
00624 int entries;
00625 int copy;
00626 {
00627 float *new_dc_table;
00628
00629 Debug((vpc, VPDEBUG_DEPTHCUE, "resizing dctable to %d entries (%s)\n",
00630 entries, copy ? "copy" : "nocopy"));
00631 if (entries == 0) {
00632 if (vpc->dc_table != NULL) {
00633 Dealloc(vpc, vpc->dc_table);
00634 vpc->dc_table = NULL;
00635 }
00636 vpc->dc_table_len = 0;
00637 } else {
00638 Alloc(vpc, new_dc_table, float *, entries * sizeof(float), "dc_table");
00639 if (vpc->dc_table != NULL) {
00640 if (copy && vpc->dc_table_len > 0) {
00641 bcopy(vpc->dc_table, new_dc_table,
00642 MIN(vpc->dc_table_len, entries) * sizeof(float));
00643 }
00644 Dealloc(vpc, vpc->dc_table);
00645 }
00646 vpc->dc_table = new_dc_table;
00647 vpc->dc_table_len = entries;
00648 }
00649 }
00650
00651
00652
00653
00654
00655
00656
00657 void
00658 VPComputeDepthCueTable(vpc, first, last)
00659 vpContext *vpc;
00660 int first;
00661 int last;
00662 {
00663 int c;
00664 double delta_depth, front_factor, density;
00665
00666 Debug((vpc, VPDEBUG_DEPTHCUE, "computing dctable entries %d to %d\n",
00667 first, last));
00668 delta_depth = vpc->dc_quantization;
00669 front_factor = vpc->dc_front_factor;
00670 density = vpc->dc_density;
00671 for (c = first; c <= last; c++)
00672 vpc->dc_table[c] = front_factor * exp(-density*(1.0 - c*delta_depth));
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 float
00686 VPSliceDepthCueRatio(vpc)
00687 vpContext *vpc;
00688 {
00689 float delta_depth;
00690 float slice_dc_ratio;
00691
00692 if (!vpc->dc_enable)
00693 return(1.);
00694 delta_depth = vpc->depth_dk - vpc->depth_di*vpc->shear_i -
00695 vpc->depth_dj*vpc->shear_j;
00696 if (vpc->reverse_slice_order)
00697 delta_depth = -delta_depth;
00698
00699 slice_dc_ratio = exp(vpc->dc_density * delta_depth);
00700 Debug((vpc, VPDEBUG_DEPTHCUE, "slice_dc_ratio = %f\n", slice_dc_ratio));
00701 return(slice_dc_ratio);
00702 }
00703
00704
00705
00706
00707
00708
00709
00710 void
00711 VPDepthCueIntImage(vpc, slicenum)
00712 vpContext *vpc;
00713 int slicenum;
00714 {
00715 float pixel_depth_quant;
00716
00717 int pixel_depth_int;
00718 float left_depth;
00719
00720 float left_depth_quant;
00721 float *dc_table;
00722 float depth_di, depth_dj;
00723
00724 float depth_quant;
00725 float depth_di_quant;
00726 float depth_dj_quant;
00727 float max_depth;
00728 int max_depth_int;
00729 int i, j;
00730 float slice_u, slice_v;
00731 GrayIntPixel *gray_intim;
00732 RGBIntPixel *rgb_intim;
00733 int width, height;
00734 int c;
00735 #ifdef DEBUG
00736 float pix_depth;
00737 #endif
00738
00739 Debug((vpc, VPDEBUG_DEPTHCUE, "depth cueing intermediate image\n"));
00740
00741
00742 width = vpc->intermediate_width;
00743 height = vpc->intermediate_height;
00744 depth_quant = 1.0 / vpc->dc_quantization;
00745 depth_di = vpc->depth_di;
00746 depth_dj = vpc->depth_dj;
00747 slice_u = vpc->shear_i * slicenum + vpc->trans_i;
00748 slice_v = vpc->shear_j * slicenum + vpc->trans_j;
00749 left_depth = vpc->depth_000 + vpc->depth_dk*slicenum -
00750 slice_u*depth_di - slice_v*depth_dj;
00751 if (depth_di > 0) {
00752 if (depth_dj > 0) {
00753 max_depth = left_depth + depth_di*width + depth_dj*height;
00754 } else {
00755 max_depth = left_depth + depth_di*width;
00756 }
00757 } else {
00758 if (depth_dj > 0) {
00759 max_depth = left_depth + depth_dj*height;
00760 } else {
00761 max_depth = left_depth;
00762 }
00763 }
00764 max_depth_int = max_depth * depth_quant;
00765 if (max_depth_int >= vpc->dc_table_len) {
00766 c = vpc->dc_table_len;
00767 VPResizeDepthCueTable(vpc, max_depth_int+1, 1);
00768 VPComputeDepthCueTable(vpc, c, vpc->dc_table_len-1);
00769 }
00770 dc_table = vpc->dc_table;
00771 depth_di_quant = depth_di * depth_quant;
00772 depth_dj_quant = depth_dj * depth_quant;
00773 left_depth_quant = left_depth * depth_quant;
00774
00775 #ifdef DEBUG
00776 Debug((vpc, VPDEBUG_DEPTHCUE, "depth cueing at image corners:\n"));
00777 pix_depth = left_depth + 0*depth_di + 0*depth_dj;
00778 pixel_depth_int = (int)(pix_depth * depth_quant);
00779 if (pixel_depth_int < 0) pixel_depth_int = 0;
00780 Debug((vpc, VPDEBUG_DEPTHCUE,
00781 " %3d %3d: depth = %10.6f, factor = %10.6f, table[%d] = %10.6f\n",
00782 0, 0, pix_depth,
00783 vpc->dc_front_factor * exp(-vpc->dc_density * (1.0 - pix_depth)),
00784 pixel_depth_int, dc_table[pixel_depth_int]));
00785 pix_depth = left_depth + width*depth_di + 0*depth_dj;
00786 pixel_depth_int = (int)(pix_depth * depth_quant);
00787 if (pixel_depth_int < 0) pixel_depth_int = 0;
00788 Debug((vpc, VPDEBUG_DEPTHCUE,
00789 " %3d %3d: depth = %10.6f, factor = %10.6f, table[%d] = %10.6f\n",
00790 width, 0, pix_depth,
00791 vpc->dc_front_factor * exp(-vpc->dc_density * (1.0 - pix_depth)),
00792 pixel_depth_int, dc_table[pixel_depth_int]));
00793 pix_depth = left_depth + width*depth_di + height*depth_dj;
00794 pixel_depth_int = (int)(pix_depth * depth_quant);
00795 if (pixel_depth_int < 0) pixel_depth_int = 0;
00796 Debug((vpc, VPDEBUG_DEPTHCUE,
00797 " %3d %3d: depth = %10.6f, factor = %10.6f, table[%d] = %10.6f\n",
00798 width, height, pix_depth,
00799 vpc->dc_front_factor * exp(-vpc->dc_density * (1.0 - pix_depth)),
00800 pixel_depth_int, dc_table[pixel_depth_int]));
00801 pix_depth = left_depth + 0*depth_di + height*depth_dj;
00802 pixel_depth_int = (int)(pix_depth * depth_quant);
00803 if (pixel_depth_int < 0) pixel_depth_int = 0;
00804 Debug((vpc, VPDEBUG_DEPTHCUE,
00805 " %3d %3d: depth = %10.6f, factor = %10.6f, table[%d] = %10.6f\n",
00806 0, height, pix_depth,
00807 vpc->dc_front_factor * exp(-vpc->dc_density * (1.0 - pix_depth)),
00808 pixel_depth_int, dc_table[pixel_depth_int]));
00809 #endif
00810
00811
00812 if (vpc->color_channels == 1) {
00813 gray_intim = vpc->int_image.gray_intim;
00814 for (j = height; j > 0; j--) {
00815 pixel_depth_quant = left_depth_quant;
00816 left_depth_quant += depth_dj_quant;
00817 for (i = width; i > 0; i--) {
00818 pixel_depth_int = pixel_depth_quant;
00819 pixel_depth_quant += depth_di_quant;
00820 if (pixel_depth_int < 0)
00821 pixel_depth_int = 0;
00822 if (pixel_depth_int >= vpc->dc_table_len) {
00823 VPBug("VPDepthCueIntImage: depth too large (%d >= %d)",
00824 pixel_depth_int, vpc->dc_table_len);
00825 }
00826 gray_intim->clrflt *= dc_table[pixel_depth_int];
00827 gray_intim++;
00828 }
00829 }
00830 } else {
00831 rgb_intim = vpc->int_image.rgb_intim;
00832 for (j = height; j > 0; j--) {
00833 pixel_depth_quant = left_depth_quant;
00834 left_depth_quant += depth_dj_quant;
00835 for (i = width; i > 0; i--) {
00836 pixel_depth_int = pixel_depth_quant;
00837 pixel_depth_quant += depth_di_quant;
00838 if (pixel_depth_int < 0)
00839 pixel_depth_int = 0;
00840 if (pixel_depth_int >= vpc->dc_table_len) {
00841 VPBug("VPDepthCueIntImage: depth too large (%d >= %d)",
00842 pixel_depth_int, vpc->dc_table_len);
00843 }
00844 rgb_intim->rclrflt *= dc_table[pixel_depth_int];
00845 rgb_intim->gclrflt *= dc_table[pixel_depth_int];
00846 rgb_intim->bclrflt *= dc_table[pixel_depth_int];
00847 rgb_intim++;
00848 }
00849 }
00850 }
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860 static void
00861 ComputeLightViewTransform(vpc, vm)
00862 vpContext *vpc;
00863 vpMatrix4 vm;
00864 {
00865 vpMatrix4 prematrix;
00866 vpMatrix4 viewportm;
00867 vpVector3 vpn;
00868 vpVector3 vup;
00869 vpVector3 tmp1v, tmp2v;
00870 vpMatrix4 view;
00871
00872
00873 vpMatrix4 tmp1m, tmp2m;
00874 double lx, ly, lz;
00875 int light_index;
00876 int maxdim;
00877 double scale;
00878
00879
00880 ASSERT(vpc->shadow_light_num >= VP_LIGHT0 &&
00881 vpc->shadow_light_num <= VP_LIGHT5);
00882 ASSERT(vpc->light_enable[vpc->shadow_light_num - VP_LIGHT0]);
00883
00884
00885 vpIdentity4(prematrix);
00886 maxdim = vpc->xlen;
00887 if (vpc->ylen > maxdim)
00888 maxdim = vpc->ylen;
00889 if (vpc->zlen > maxdim)
00890 maxdim = vpc->zlen;
00891 scale = 1. / (double)maxdim;
00892 prematrix[0][0] = scale;
00893 prematrix[1][1] = scale;
00894 prematrix[2][2] = scale;
00895 prematrix[0][3] = -vpc->xlen * scale * 0.5;
00896 prematrix[1][3] = -vpc->ylen * scale * 0.5;
00897 prematrix[2][3] = -vpc->zlen * scale * 0.5;
00898
00899
00900 light_index = vpc->shadow_light_num - VP_LIGHT0;
00901 lx = vpc->light_vector[light_index][0];
00902 ly = vpc->light_vector[light_index][1];
00903 lz = vpc->light_vector[light_index][2];
00904 vpSetVector3(vpn, lx, ly, lz);
00905 if (fabs(lx) < fabs(ly)) {
00906 if (fabs(lx) < fabs(lz)) {
00907 vpSetVector3(vup, 1.0, 0.0, 0.0);
00908 } else {
00909 vpSetVector3(vup, 0.0, 0.0, 1.0);
00910 }
00911 } else {
00912 if (fabs(ly) < fabs(lz)) {
00913 vpSetVector3(vup, 0.0, 1.0, 0.0);
00914 } else {
00915 vpSetVector3(vup, 0.0, 0.0, 1.0);
00916 }
00917 }
00918 vpCrossProduct(tmp1v, vup, vpn);
00919 vpCrossProduct(tmp2v, vpn, tmp1v);
00920
00921 vpIdentity4(view);
00922 view[0][0] = tmp1v[0];
00923 view[0][1] = tmp1v[1];
00924 view[0][2] = tmp1v[2];
00925 view[1][0] = tmp2v[0];
00926 view[1][1] = tmp2v[1];
00927 view[1][2] = tmp2v[2];
00928 view[2][0] = vpn[0];
00929 view[2][1] = vpn[1];
00930 view[2][2] = vpn[2];
00931
00932
00933 vpIdentity4(viewportm);
00934 viewportm[2][2] = -1.0;
00935
00936
00937 vpMatrixMult4(tmp1m, vpc->transforms[VP_MODEL], prematrix);
00938 vpMatrixMult4(tmp2m, view, tmp1m);
00939 vpMatrixMult4(vm, viewportm, tmp2m);
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 static int
00951 FactorLightView(vpc, vm)
00952 vpContext *vpc;
00953 vpMatrix4 vm;
00954 {
00955 vpMatrix4 p;
00956 vpMatrix4 pvm;
00957 int icount, jcount, kcount;
00958 double denom;
00959
00960 Debug((vpc, VPDEBUG_SHADOW, "FactorLightView\n"));
00961
00962
00963
00964 bzero(p, sizeof(vpMatrix4));
00965 switch (vpc->best_view_axis) {
00966 case VP_X_AXIS:
00967 p[0][2] = 1.;
00968 p[1][0] = 1.;
00969 p[2][1] = 1.;
00970 p[3][3] = 1.;
00971 icount = vpc->ylen;
00972 jcount = vpc->zlen;
00973 kcount = vpc->xlen;
00974 break;
00975 case VP_Y_AXIS:
00976 p[0][1] = 1.;
00977 p[1][2] = 1.;
00978 p[2][0] = 1.;
00979 p[3][3] = 1.;
00980 icount = vpc->zlen;
00981 jcount = vpc->xlen;
00982 kcount = vpc->ylen;
00983 break;
00984 case VP_Z_AXIS:
00985 p[0][0] = 1.;
00986 p[1][1] = 1.;
00987 p[2][2] = 1.;
00988 p[3][3] = 1.;
00989 icount = vpc->xlen;
00990 jcount = vpc->ylen;
00991 kcount = vpc->zlen;
00992 break;
00993 }
00994 vpMatrixMult4(pvm, vm, p);
00995
00996
00997 denom = pvm[0][0]*pvm[1][1] - pvm[0][1]*pvm[1][0];
00998 if (fabs(denom) < VP_EPS)
00999 return(VPSetError(vpc, VPERROR_SINGULAR));
01000 vpc->shadow_shear_i = (pvm[0][2]*pvm[1][1] - pvm[0][1]*pvm[1][2]) / denom;
01001 vpc->shadow_shear_j = (pvm[0][0]*pvm[1][2] - pvm[1][0]*pvm[0][2]) / denom;
01002
01003
01004 if (pvm[2][0]*vpc->shadow_shear_i + pvm[2][1]*vpc->shadow_shear_j -
01005 pvm[2][2] > 0) {
01006 if (vpc->reverse_slice_order != 0)
01007 return(VPERROR_BAD_SHADOW);
01008 } else {
01009 if (vpc->reverse_slice_order != 1)
01010 return(VPERROR_BAD_SHADOW);
01011 }
01012
01013
01014 vpc->shadow_width = (int)ceil((kcount-1)*fabs(vpc->shadow_shear_i)) +
01015 icount + 1;
01016 vpc->shadow_height = (int)ceil((kcount-1)*fabs(vpc->shadow_shear_j)) +
01017 jcount + 1;
01018
01019
01020 if (vpc->shadow_shear_i >= 0.)
01021 vpc->shadow_trans_i = 1.;
01022 else
01023 vpc->shadow_trans_i = 1. - vpc->shadow_shear_i * (kcount - 1);
01024 if (vpc->shadow_shear_j >= 0.)
01025 vpc->shadow_trans_j = 1.;
01026 else
01027 vpc->shadow_trans_j = 1. - vpc->shadow_shear_j * (kcount - 1);
01028
01029 Debug((vpc, VPDEBUG_SHADOW, " shadow shear factors: %g %g\n",
01030 vpc->shadow_shear_i, vpc->shadow_shear_j));
01031 Debug((vpc, VPDEBUG_SHADOW, " shadow translation: %g %g\n",
01032 vpc->shadow_trans_i, vpc->shadow_trans_j));
01033
01034 return(VP_OK);
01035 }
01036
01037
01038
01039
01040
01041
01042
01043 static void
01044 CheckShadowBuffer(vpc)
01045 vpContext *vpc;
01046 {
01047 int new_max_width, new_max_height;
01048 int resize = 0;
01049
01050
01051 if (vpc->shadow_width > vpc->max_shadow_width) {
01052 new_max_width = MAX(vpc->shadow_width, vpc->shadow_width_hint);
01053 resize = 1;
01054 } else {
01055 new_max_width = MAX(vpc->max_shadow_width, vpc->shadow_width_hint);
01056 }
01057 if (vpc->shadow_height > vpc->max_shadow_height) {
01058 new_max_height = MAX(vpc->shadow_height, vpc->shadow_height_hint);
01059 resize = 1;
01060 } else {
01061 new_max_height = MAX(vpc->max_shadow_height, vpc->shadow_height_hint);
01062 }
01063
01064
01065 if (resize)
01066 VPResizeShadowBuffer(vpc, new_max_width, new_max_height);
01067 }
01068
01069
01070
01071
01072
01073
01074
01075 void
01076 VPResizeShadowBuffer(vpc, max_width, max_height)
01077 vpContext *vpc;
01078 int max_width;
01079 int max_height;
01080 {
01081
01082 if (vpc->shadow_buffer != NULL) {
01083 Dealloc(vpc, vpc->shadow_buffer);
01084 }
01085
01086
01087 vpc->max_shadow_width = max_width;
01088 vpc->max_shadow_height = max_height;
01089 if (max_width > 0) {
01090 Alloc(vpc, vpc->shadow_buffer, GrayIntPixel *,
01091 max_width * max_height * sizeof(GrayIntPixel), "shadow_buffer");
01092 } else {
01093 vpc->shadow_buffer = NULL;
01094 }
01095 }