Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:jdpipe
povray
povray-wweiser-patchset-6.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File povray-wweiser-patchset-6.diff of Package povray
diff -urN povray-3.6.1/source/Makefile.am povray-3.6.1-ww/source/Makefile.am --- povray-3.6.1/source/Makefile.am 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/Makefile.am 2004-08-11 21:40:47.000000000 +0200 @@ -33,7 +33,8 @@ # Source files. libpovray_a_SOURCES = \ -atmosph.cpp atmosph.h bbox.cpp bbox.h bcyl.cpp bcyl.h benchmark.cpp benchmark.h bezier.cpp bezier.h blob.cpp blob.h boxes.cpp boxes.h bsphere.cpp bsphere.h camera.cpp camera.h chi2.cpp chi2.h colour.cpp colour.h colutils.cpp colutils.h cones.cpp cones.h csg.cpp csg.h discs.cpp discs.h express.cpp express.h fncode.cpp fncode.h fnintern.cpp fnintern.h fnpovfpu.cpp fnpovfpu.h fnsyntax.cpp fnsyntax.h fpmetric.cpp fpmetric.h fractal.cpp fractal.h frame.h function.cpp function.h gif.cpp gifdecod.cpp gifdecod.h gif.h hcmplx.cpp hcmplx.h hfield.cpp hfield.h histogra.cpp histogra.h iff.cpp iff.h image.cpp image.h interior.cpp interior.h isosurf.cpp isosurf.h jpeg_pov.cpp jpeg_pov.h lathe.cpp lathe.h lbuffer.cpp lbuffer.h lightgrp.cpp lightgrp.h lighting.cpp lighting.h mathutil.cpp mathutil.h matrices.cpp matrices.h media.cpp media.h mesh.cpp mesh.h normal.cpp normal.h objects.cpp objects.h octree.cpp octree.h optout.cpp optout.h parse.cpp parse.h parsestr.cpp parsestr.h parstxtr.cpp parstxtr.h pattern.cpp pattern.h pgm.cpp pgm.h photons.cpp photons.h pigment.cpp pigment.h planes.cpp planes.h png_pov.cpp png_pov.h point.cpp point.h poly.cpp polygon.cpp polygon.h poly.h polysolv.cpp polysolv.h pov_mem.cpp pov_mem.h povmsend.cpp povmsend.h povmsrec.cpp povmsrec.h povray.cpp povray.h pov_util.cpp pov_util.h ppm.cpp ppm.h prism.cpp prism.h quadrics.cpp quadrics.h quatern.cpp quatern.h rad_data.cpp radiosit.cpp radiosit.h ray.cpp ray.h rendctrl.cpp rendctrl.h render.cpp render.h renderio.cpp renderio.h sor.cpp sor.h spheres.cpp spheres.h sphsweep.cpp sphsweep.h splines.cpp splines.h statspov.cpp statspov.h super.cpp super.h targa.cpp targa.h texture.cpp texture.h tiff_pov.cpp tiff_pov.h tokenize.cpp tokenize.h torus.cpp torus.h triangle.cpp triangle.h truetype.cpp truetype.h txttest.cpp txttest.h userdisp.cpp userdisp.h userio.cpp userio.h vbuffer.cpp vbuffer.h vector.h vlbuffer.cpp vlbuffer.h warps.cpp warps.h + atmosph.cpp atmosph.h bbox.cpp bbox.h bcyl.cpp bcyl.h benchmark.cpp benchmark.h bezier.cpp bezier.h blob.cpp blob.h boxes.cpp boxes.h bsphere.cpp bsphere.h camera.cpp camera.h chi2.cpp chi2.h colour.cpp colour.h colutils.cpp colutils.h cones.cpp cones.h csg.cpp csg.h discs.cpp discs.h express.cpp express.h fncode.cpp fncode.h fnintern.cpp fnintern.h fnpovfpu.cpp fnpovfpu.h fnsyntax.cpp fnsyntax.h fpmetric.cpp fpmetric.h fractal.cpp fractal.h frame.h function.cpp function.h gif.cpp gifdecod.cpp gifdecod.h gif.h hcmplx.cpp hcmplx.h hfield.cpp hfield.h histogra.cpp histogra.h iff.cpp iff.h image.cpp image.h interior.cpp interior.h isosurf.cpp isosurf.h jpeg_pov.cpp jpeg_pov.h lathe.cpp lathe.h lbuffer.cpp lbuffer.h lightgrp.cpp lightgrp.h lighting.cpp lighting.h mathutil.cpp mathutil.h matrices.cpp matrices.h media.cpp media.h mesh.cpp mesh.h normal.cpp normal.h objects.cpp objects.h octree.cpp octree.h optout.cpp optout.h parse.cpp parse.h parsestr.cpp parsestr.h parstxtr.cpp parstxtr.h pattern.cpp pattern.h pgm.cpp pgm.h photons.cpp photons.h pigment.cpp pigment.h planes.cpp planes.h png_pov.cpp png_pov.h point.cpp point.h poly.cpp polygon.cpp polygon.h poly.h polysolv.cpp polysolv.h pov_mem.cpp pov_mem.h povmsend.cpp povmsend.h povmsrec.cpp povmsrec.h povray.cpp povray.h pov_util.cpp pov_util.h ppm.cpp ppm.h prism.cpp prism.h quadrics.cpp quadrics.h quatern.cpp quatern.h rad_data.cpp radiosit.cpp radiosit.h ray.cpp ray.h rendctrl.cpp rendctrl.h render.cpp render.h renderio.cpp renderio.h sor.cpp sor.h spheres.cpp spheres.h sphsweep.cpp sphsweep.h splines.cpp splines.h statspov.cpp statspov.h super.cpp super.h targa.cpp targa.h texture.cpp texture.h tiff_pov.cpp tiff_pov.h tokenize.cpp tokenize.h torus.cpp torus.h triangle.cpp triangle.h truetype.cpp truetype.h txttest.cpp txttest.h userdisp.cpp userdisp.h userio.cpp userio.h vbuffer.cpp vbuffer.h vector.h vlbuffer.cpp vlbuffer.h warps.cpp warps.h \ + prt_tileheap.h prt_tileheap.cpp prt_render.h prt_render.cpp prt_imagestore.h prt_imagestore.cpp # Include paths for headers. AM_CPPFLAGS = \ diff -urN povray-3.6.1/source/bezier.cpp povray-3.6.1-ww/source/bezier.cpp --- povray-3.6.1/source/bezier.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/bezier.cpp 2004-10-18 21:53:26.000000000 +0200 @@ -1229,7 +1229,7 @@ Assign_Vector(vertices[2], (*Patch)[3][0]); - VSub(TempV, vertices[0], vertices[1]); + VSub(TempV, vertices[0], vertices[2]); VLength(temp1, TempV); @@ -1251,7 +1251,7 @@ { Assign_Vector(vertices[2], (*Patch)[3][0]); - VSub(TempV, vertices[0], vertices[1]); + VSub(TempV, vertices[0], vertices[2]); VLength(temp1, TempV); @@ -1279,6 +1279,8 @@ } else { + // NOTE: These 8 lines are identical in all if/else branches and + // could be moved out below. VSub(TempV, vertices[1], vertices[2]); VLength(temp1, TempV); diff -urN povray-3.6.1/source/fpmetric.cpp povray-3.6.1-ww/source/fpmetric.cpp --- povray-3.6.1/source/fpmetric.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/fpmetric.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -74,6 +74,10 @@ const int SIDE_Z_0 = 5; const int SIDE_Z_1 = 6; +/* Minimal intersection depth. */ + +static const double DEPTH_TOLERANCE = 1.0e-6; + /***************************************************************************** * Static functions @@ -112,8 +116,9 @@ static PARAMETRIC* PrecompParFunc; // GLOBAL VARIABLE static int PrecompLastDepth; // GLOBAL VARIABLE -static DBL Intervals_Low[2][32], Intervals_Hi[2][32]; // GLOBAL VARIABLE -static int SectorNum[32]; // GLOBAL VARIABLE +static const int SECT_DIM=48; // [WW] parametric crash fix +static DBL Intervals_Low[2][SECT_DIM], Intervals_Hi[2][SECT_DIM]; // GLOBAL VARIABLE +static int SectorNum[SECT_DIM]; // GLOBAL VARIABLE /***************************************************************************** @@ -210,6 +215,29 @@ if (Depth1 == Depth2) Depth1 = 0; + /* Against self-shadowing of parametric object as proposed by + * Massimo Valenti <sixtysix@inwind.it>. + * He wrote: + * + * The problem is that the surface is getting self shadowed for accuracy + * problems. The black color is the result of the surface being shadowed + * by itself. + * + * The intersections between a ray and the parametric surface are not + * computed exactly, the algorithm would eventually converge to the + * solution, but you need to stop it at some point. So you obtain an + * approximated intersection, that's likely NOT on the surface, it is + * near, but either in front or behind the surface. + * Shooting a ray from the approximated (behind) intersection point to the + * light, it will find the same surface at a small distance from the start. + * + * So the sense of the fix is to reduce the range in which to search a + * valid intersection. It is something that is done for nearly every + * primitive in POVray. + */ + if (Depth1 < DEPTH_TOLERANCE) + Depth1 = DEPTH_TOLERANCE; + if ((Depth1 += 4 * Par->accuracy) > Depth2) return false; @@ -346,7 +374,7 @@ } /* Z */ - if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) + if (SectorNum[i] < MaxPrecompZ) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; @@ -404,7 +432,7 @@ if (Len > TLen) Len = TLen; - if (Len < Par->accuracy) + if (Len < Par->accuracy || i>=SECT_DIM-1) // [WW] parametric crash fix { if ((TResult > TPotRes) && (TPotRes > Depth1)) { diff -urN povray-3.6.1/source/frame.h povray-3.6.1-ww/source/frame.h --- povray-3.6.1/source/frame.h 2004-07-18 12:16:25.000000000 +0200 +++ povray-3.6.1-ww/source/frame.h 2004-08-11 21:22:26.000000000 +0200 @@ -1312,6 +1312,7 @@ struct { void *Fn; void *Data; } Function;\ PIGMENT *Pigment; \ OBJECT *Object;\ + short Grid_Type; \ } Vals; struct Pattern_Struct diff -urN povray-3.6.1/source/frontend/defaultrenderfrontend.cpp povray-3.6.1-ww/source/frontend/defaultrenderfrontend.cpp --- povray-3.6.1/source/frontend/defaultrenderfrontend.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/frontend/defaultrenderfrontend.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -229,6 +229,7 @@ BannerPrintf("\n"); BannerPrintf(" A[0.n] = perform antialiasing (if color change is above n percent)\n"); BannerPrintf(" AMn = use non-adaptive (n=1) or adaptive (n=2) supersampling\n"); + BannerPrintf(" or use PRT (n=4)\n"); BannerPrintf(" J[n.n] = set antialiasing-jitter (and amount)\n"); BannerPrintf(" Rn = set antialiasing-depth (use n X n rays/pixel)\n"); BannerPrintf("\n"); diff -urN povray-3.6.1/source/isosurf.cpp povray-3.6.1-ww/source/isosurf.cpp --- povray-3.6.1/source/isosurf.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/isosurf.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -126,7 +126,8 @@ * ******************************************************************************/ -static int All_IsoSurface_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) +static int All_IsoSurface_Intersections(OBJECT* Object, RAY* Ray, + ISTACK* Depth_Stack) { ISOSURFACE * Isosrf = (ISOSURFACE *)Object; int Side1 = 0, Side2 = 0, itrace = 0, i_flg = 0; @@ -243,7 +244,8 @@ { /* IPoint is on the isosurface */ VEvaluateRay(VTmp, P, tmin, D); - if(fabs(Vector_IsoSurface_Function(Isosrf, VTmp)) < (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) + if(fabs(Vector_IsoSurface_Function(Isosrf, VTmp)) < + (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) { tmin = Isosrf->accuracy * 5.0; VEvaluateRay(VTmp, P, tmin, D); @@ -255,7 +257,8 @@ for (; itrace < Isosrf->max_trace; itrace++) { - if(IsoSurface_Function_Find_Root(Isosrf, P, D, &tmin, &tmax, in_shadow_test) == false) + if(IsoSurface_Function_Find_Root(Isosrf, P, D, &tmin, &tmax, + in_shadow_test) == false) break; else { @@ -799,8 +802,8 @@ (((prop <= 0.95) || (diff <= -0.1)) && (mginfo->max_gradient < 10.0))) { WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, - "The maximum gradient found was %0.3f, but max_gradient of the\n" - "isosurface was set to %0.3f. The isosurface may contain holes!\n" + "The maximum gradient found was %0.3g, but max_gradient of the\n" + "isosurface was set to %0.3g. The isosurface may contain holes!\n" "Adjust max_gradient to get a proper rendering of the isosurface.", (float)(mginfo->gradient), (float)(mginfo->max_gradient)); @@ -808,8 +811,8 @@ else if((diff >= 10.0) || ((prop >= 1.1) && (diff >= 0.5))) { WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, - "The maximum gradient found was %0.3f, but max_gradient of\n" - "the isosurface was set to %0.3f. Adjust max_gradient to\n" + "The maximum gradient found was %0.3g, but max_gradient of\n" + "the isosurface was set to %0.3g. Adjust max_gradient to\n" "get a faster rendering of the isosurface.", (float)(mginfo->gradient), (float)(mginfo->max_gradient)); @@ -826,8 +829,8 @@ mginfo->eval_cnt = max(mginfo->eval_cnt, 1.0); // make sure it won't be zero WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, - "Evaluate found a maximum gradient of %0.3f and an average\n" - "gradient of %0.3f. The maximum gradient variation was %0.3f.\n", + "Evaluate found a maximum gradient of %0.3g and an average\n" + "gradient of %0.3g. The maximum gradient variation was %0.3g.\n", (float)(mginfo->eval_max), (float)(mginfo->eval_gradient_sum / mginfo->eval_cnt), (float)(mginfo->eval_var)); @@ -837,9 +840,9 @@ diff = max(diff, 1.0); // prevent contradicting output Debug_Info("It is recommended to adjust the parameters of 'evaluate' to:\n" - "First parameter less than %0.3f\n" - "Second parameter less than %0.3f and greater than 1.0\n" - "Third parameter greater than %0.3f and less than 1.0\n", + "First parameter less than %0.3g\n" + "Second parameter less than %0.3g and greater than 1.0\n" + "Third parameter greater than %0.3g and less than 1.0\n", (float)(mginfo->eval_max), (float)(diff), (float)(1.0 / diff)); @@ -903,7 +906,8 @@ BBOX_VECT& Low_Left = IsoSurface->BBox.Lower_Left; Assign_BBox_Vect(Low_Left, IsoSurface->container.box.corner1); - VSub(IsoSurface->BBox.Lengths, IsoSurface->container.box.corner2, IsoSurface->container.box.corner1); + VSub(IsoSurface->BBox.Lengths, IsoSurface->container.box.corner2, + IsoSurface->container.box.corner1); } if(IsoSurface->Trans != NULL) @@ -939,7 +943,8 @@ * ******************************************************************************/ -int IsoSurface_Function_Find_Root(ISOSURFACE* ISOSRF, VECTOR P, VECTOR D, DBL* Depth1, DBL* Depth2, bool in_shadow_test) +int IsoSurface_Function_Find_Root(ISOSURFACE* ISOSRF, VECTOR P, VECTOR D, + DBL* Depth1, DBL* Depth2, bool in_shadow_test) { DBL dt, t21, l_b, l_e, oldmg; ISO_Pair EP1, EP2; @@ -987,7 +992,8 @@ if((ISOSRF->eval == true) && (ISOSRF->max_gradient > ISOSRF->eval_param[0])) ISOSRF->max_gradient *= ISOSRF->eval_param[2]; dt = ISOSRF->max_gradient * ISOSRF->Vlength * t21; - if(IsoSurface_Function_Find_Root_R(ISOSRF, &EP1, &EP2, dt, t21, 1.0 / (ISOSRF->Vlength * t21), in_shadow_test)) + if(IsoSurface_Function_Find_Root_R(ISOSRF, &EP1, &EP2, dt, t21, 1.0 / + (ISOSRF->Vlength * t21), in_shadow_test)) { if(ISOSRF->eval == true) { @@ -1045,7 +1051,8 @@ * ******************************************************************************/ -int IsoSurface_Function_Find_Root_R(ISOSURFACE* ISOSRF, ISO_Pair* EP1, ISO_Pair* EP2, DBL dt, DBL t21, DBL len, bool in_shadow_test) +int IsoSurface_Function_Find_Root_R(ISOSURFACE* ISOSRF, ISO_Pair* EP1, + ISO_Pair* EP2, DBL dt, DBL t21, DBL len, bool in_shadow_test) { ISO_Pair EPa; DBL temp; @@ -1054,24 +1061,38 @@ if(ISOSRF->gradient < temp) ISOSRF->gradient = temp; - if((ISOSRF->eval == true) && (ISOSRF->max_gradient < temp * ISOSRF->eval_param[1])) + if((ISOSRF->eval == true) && (ISOSRF->max_gradient < + temp * ISOSRF->eval_param[1])) { - ISOSRF->max_gradient = temp * ISOSRF->eval_param[1] * ISOSRF->eval_param[1]; + ISOSRF->max_gradient = temp * ISOSRF->eval_param[1] * + ISOSRF->eval_param[1]; dt = ISOSRF->max_gradient * ISOSRF->Vlength * t21; } if(t21 < ISOSRF->accuracy) { - if(EP2->f < 0) + if(EP2->f <= 0.0) { - ISOSRF->tl = EP2->t; + // Accuracy improvement using linear interpolation. + // Wolfgang Wieser 02/2004 + if(EP1->f >= 0.0) + { + double df = EP1->f-EP2->f; + // Need to calc (EP1->t*EP2->f - EP2->t*EP1->f) / df + // in a numerically stable way. + if(df>1e-14) + ISOSRF->tl = EP2->t + t21*EP2->f/df; + else + ISOSRF->tl = 0.5*(EP2->t+EP1->t); + } + else + ISOSRF->tl = EP2->t; return true; } - else - return false; + return false; } - if((EP1->f + EP2->f - dt) < 0) + if(EP1->f + EP2->f < dt) { t21 *= 0.5; dt *= 0.5; @@ -1079,8 +1100,10 @@ EPa.f = Float_IsoSurface_Function(ISOSRF, &EPa.t); ISOSRF->fmax = min(EPa.f, ISOSRF->fmax); - if(!IsoSurface_Function_Find_Root_R(ISOSRF, EP1, &EPa, dt, t21, len * 2.0, in_shadow_test)) - return (IsoSurface_Function_Find_Root_R(ISOSRF, &EPa, EP2, dt, t21, len * 2.0, in_shadow_test)); + if(!IsoSurface_Function_Find_Root_R(ISOSRF, EP1, &EPa, dt, + t21, len * 2.0, in_shadow_test)) + return (IsoSurface_Function_Find_Root_R(ISOSRF, &EPa, EP2, dt, + t21, len * 2.0, in_shadow_test)); else return true; } diff -urN povray-3.6.1/source/lighting.cpp povray-3.6.1-ww/source/lighting.cpp --- povray-3.6.1/source/lighting.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/lighting.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -209,7 +209,7 @@ COLOUR Light_Colour); static int do_blocking (INTERSECTION *Local_Intersection, - RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack); + RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack, int Media_Attenuation_Flag); static void do_irid (FINISH *Finish, RAY *Light_Source_Ray, VECTOR Layer_Normal, VECTOR IPoint, COLOUR Colour); @@ -226,7 +226,7 @@ static int Refract (INTERIOR*, VECTOR, RAY*, VECTOR, VECTOR, COLOUR, DBL); static void filter_shadow_ray (INTERSECTION *Ray_Intersection, - RAY *Light_Source_Ray, COLOUR Colour); + RAY *Light_Source_Ray, COLOUR Colour, int Media_Attenuation_Flag); static int create_texture_list (INTERSECTION *Ray_Intersection, DBL realNormDir); @@ -250,7 +250,7 @@ DBL Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR P, COLOUR Colour); static void do_light_ray_atmosphere (RAY *Light_Source_Ray, - INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object); + INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object, int Media_Attenuation_Flag); static void determine_reflectivity (DBL *weight, RGB reflectivity, COLOUR Reflection_Max, COLOUR Reflection_Min, @@ -834,7 +834,7 @@ ((*Light_Source_Depth - Local_Intersection->Depth) > Projected_Depth) && (Local_Intersection->Depth > SHADOW_TOLERANCE)) { - if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack)) + if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack, Light_Source->Media_Attenuation)) { Quit_Looking = true; @@ -951,7 +951,7 @@ { Increase_Counter(stats[Shadow_Rays_Succeeded]); - filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour); + filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour, Light_Source->Media_Attenuation); if ((fabs(Light_Colour[pRED]) < EPSILON) && (fabs(Light_Colour[pGREEN]) < EPSILON) && @@ -1086,7 +1086,7 @@ ((*Light_Source_Depth - Local_Intersection->Depth) > Projected_Depth) && (Local_Intersection->Depth > SHADOW_TOLERANCE)) { - if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack)) + if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack, Light_Source->Media_Attenuation)) { Quit_Looking = true; @@ -1149,7 +1149,7 @@ { Increase_Counter(stats[Shadow_Rays_Succeeded]); - filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour); + filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour, Light_Source->Media_Attenuation); if ((fabs(Light_Colour[pRED]) < EPSILON) && (fabs(Light_Colour[pGREEN]) < EPSILON) && @@ -1204,7 +1204,7 @@ { Increase_Counter(stats[Shadow_Rays_Succeeded]); - filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour); + filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour, Light_Source->Media_Attenuation); if ((fabs(Light_Colour[pRED]) < EPSILON) && (fabs(Light_Colour[pGREEN]) < EPSILON) && @@ -5104,7 +5104,7 @@ * ******************************************************************************/ -static void filter_shadow_ray(INTERSECTION *Ray_Intersection, RAY *Light_Source_Ray, COLOUR Colour) +static void filter_shadow_ray(INTERSECTION *Ray_Intersection, RAY *Light_Source_Ray, COLOUR Colour, int Media_Attenuation_Flag) { int i, Texture_Count; VECTOR IPoint; @@ -5257,7 +5257,8 @@ /* Get atmospheric attenuation. */ - do_light_ray_atmosphere(Light_Source_Ray, Ray_Intersection, Colour, true); + do_light_ray_atmosphere(Light_Source_Ray, Ray_Intersection, Colour, true, Media_Attenuation_Flag); + } @@ -5288,11 +5289,11 @@ * ******************************************************************************/ -static int do_blocking(INTERSECTION *Local_Intersection, RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack) +static int do_blocking(INTERSECTION *Local_Intersection, RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack, int Media_Attenuation_Flag) { Increase_Counter(stats[Shadow_Rays_Succeeded]); - filter_shadow_ray(Local_Intersection, Light_Source_Ray, Light_Colour); + filter_shadow_ray(Local_Intersection, Light_Source_Ray, Light_Colour, Media_Attenuation_Flag); if ((fabs(Light_Colour[pRED]) < EPSILON) && (fabs(Light_Colour[pGREEN]) < EPSILON) && @@ -5398,7 +5399,7 @@ Isection.Depth = New_Depth; Isection.Object = NULL; - do_light_ray_atmosphere(&New_Ray, &Isection, Colour, false); + do_light_ray_atmosphere(&New_Ray, &Isection, Colour, false, true); } } @@ -5549,7 +5550,7 @@ * ******************************************************************************/ -static void do_light_ray_atmosphere(RAY *Light_Source_Ray, INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object) +static void do_light_ray_atmosphere(RAY *Light_Source_Ray, INTERSECTION *Ray_Intersection, COLOUR Colour, int Valid_Object, int Media_Attenuation_Flag) { int interior_nr; int i, all_hollow; @@ -5575,7 +5576,8 @@ /* Apply atmospheric effects inside and/or outside any object. */ - if ((opts.Quality_Flags & Q_VOLUME) && (all_hollow || (Valid_Object && Ray_Intersection->Object->Interior != NULL))) + /* Patch for media_attenuation bug (A. Brinkmann) */ + if (Media_Attenuation_Flag && (opts.Quality_Flags & Q_VOLUME) && (all_hollow || (Valid_Object && Ray_Intersection->Object->Interior != NULL))) { Do_Finite_Atmosphere(Light_Source_Ray, Ray_Intersection, Colour, true); } diff -urN povray-3.6.1/source/parse.h povray-3.6.1-ww/source/parse.h --- povray-3.6.1/source/parse.h 2004-07-18 12:16:26.000000000 +0200 +++ povray-3.6.1-ww/source/parse.h 2004-08-11 21:22:26.000000000 +0200 @@ -246,6 +246,7 @@ GIF_TOKEN, GRADIENT_TOKEN, GRANITE_TOKEN, + GRID_PATTERN_TOKEN, HASH_TOKEN, HAT_TOKEN, HEIGHT_FIELD_TOKEN, @@ -597,6 +598,7 @@ PATTERN_TOKEN, FACETS_TOKEN, SLOPE_TOKEN, + RADIAL_SLOPE_TOKEN, SOLID_TOKEN, COORDS_TOKEN, SIZE_TOKEN, diff -urN povray-3.6.1/source/parstxtr.cpp povray-3.6.1-ww/source/parstxtr.cpp --- povray-3.6.1/source/parstxtr.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/parstxtr.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -976,6 +976,11 @@ EXIT END_CASE + CASE (RADIAL_SLOPE_TOKEN) + New->Type = RADIAL_SLOPE_PATTERN; + EXIT + END_CASE + CASE (CRACKLE_TOKEN) New->Type = CRACKLE_PATTERN; New->Vals.Crackle.IsSolid = 0; @@ -1181,6 +1186,25 @@ EXIT END_CASE + CASE (GRID_PATTERN_TOKEN) + New->Type = GRID_PATTERN; + New->Frequency = 1.0; + EXPECT + CASE (CYLINDRICAL_TOKEN) + New->Vals.Grid_Type = 1; + EXIT + END_CASE + CASE (PLANAR_TOKEN) + New->Vals.Grid_Type = 0; + EXIT + END_CASE + OTHERWISE + Error("Invalid grid_pattern type. Valid types are 'planar' and 'cylindrical'."); + END_CASE + END_EXPECT + EXIT + END_CASE + CASE (DENSITY_FILE_TOKEN) if (Old_Type==DENSITY_FILE_PATTERN) { diff -urN povray-3.6.1/source/pattern.cpp povray-3.6.1-ww/source/pattern.cpp --- povray-3.6.1/source/pattern.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/pattern.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -88,6 +88,7 @@ static DBL function_pattern (VECTOR EPoint, TPATTERN *TPat); // iso_surface - added static DBL gradient_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL granite_pattern (VECTOR EPoint, TPATTERN *TPat); +static DBL grid_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL hexagon_pattern (VECTOR EPoint); static DBL julia_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL julia3_pattern (VECTOR EPoint, TPATTERN *TPat); @@ -111,6 +112,7 @@ static DBL radial_pattern (VECTOR EPoint); static DBL ripples_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL slope_pattern (VECTOR EPoint, TPATTERN *TPat, INTERSECTION *Intersection); +static DBL radial_slope_pattern (VECTOR EPoint, TPATTERN *TPat, INTERSECTION *Intersection); static DBL spiral1_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL spiral2_pattern (VECTOR EPoint, TPATTERN *TPat); static DBL spherical_pattern (VECTOR EPoint); @@ -175,6 +177,7 @@ case CRACKLE_PATTERN: value = crackle_pattern (EPoint, TPat); break; case GRADIENT_PATTERN: value = gradient_pattern (EPoint, TPat); break; case GRANITE_PATTERN: value = granite_pattern (EPoint, TPat); break; + case GRID_PATTERN: value = grid_pattern (EPoint, TPat); break; case HEXAGON_PATTERN: value = hexagon_pattern (EPoint); break; case JULIA_PATTERN: value = julia_pattern (EPoint, TPat); break; case JULIA3_PATTERN: value = julia3_pattern (EPoint, TPat); break; @@ -208,6 +211,7 @@ case DENSITY_FILE_PATTERN:value = density_pattern (EPoint, TPat); break; case IMAGE_PATTERN: value = image_pattern (EPoint, TPat); break; case SLOPE_PATTERN: value = slope_pattern (EPoint, TPat, Isection); break; + case RADIAL_SLOPE_PATTERN:value = radial_slope_pattern(EPoint, TPat, Isection); break; case PIGMENT_PATTERN: value = pigment_pattern (EPoint, TPat, Isection); break; case OBJECT_PATTERN: value = object_pattern (EPoint, TPat); break; @@ -1890,6 +1894,74 @@ * * FUNCTION * +* grid_pattern +* +* INPUT +* +* EPoint -- The point in 3d space at which the pattern +* is evaluated. +* +* OUTPUT +* +* RETURNS +* +* Double value between 0.0 and 1.0. +* +* AUTHOR +* +* Wolfgang Wieser +* +* DESCRIPTION +* +* Grid pattern can be used for easy creation of cylindrical +* (Vals.Grid_Type = 1) and planar (Vals.Grid_Type = 0) grids. +* +******************************************************************************/ + +inline DBL _fract(register DBL x) +{ return(x-floor(x)); } + +static DBL grid_pattern (VECTOR EPoint, TPATTERN *TPat) +{ + DBL mindist=0.5; + + switch(TPat->Vals.Grid_Type) + { + case 0: /* planar */ + { + DBL xlen=_fract( EPoint[X] ); + DBL zlen=_fract( EPoint[Z] ); + + if(xlen>0.5) xlen=1.0-xlen; + if(zlen>0.5) zlen=1.0-zlen; + mindist = min(xlen,zlen); + mindist+=mindist; + } break; + case 1: /* cylindrical */ + { + /*DBL rad=_fract( hypot(EPoint[X],EPoint[Z]) );*/ + DBL ylen=_fract( EPoint[Y] ); + DBL phi=atan2(EPoint[Z],EPoint[X]); // -pi..+pi + DBL sector=_fract( TPat->Frequency*(phi+M_PI)/M_PI ); + + if(sector>0.5) sector=1.0-sector; + if(ylen>0.5) ylen=1.0-ylen; + mindist = min(sector,ylen); + mindist+=mindist; + } break; + } + + if(mindist>1.0) mindist=1.0; + else if(mindist<0.0) mindist=0.0; + + return(mindist/TPat->Frequency); +} + + +/***************************************************************************** +* +* FUNCTION +* * hexagon_pattern * * INPUT @@ -3317,7 +3389,7 @@ } else { - value = 0.25 + (atan2(EPoint[X],EPoint[Z]) + M_PI) / TWO_M_PI; + value = (atan2(EPoint[Z],-EPoint[X]) + M_PI) / TWO_M_PI; } return(value); @@ -3385,6 +3457,73 @@ * * FUNCTION * +* radial_slope_pattern +* +* INPUT +* +* EPoint -- The point in 3d space at which the pattern +* is evaluated. +* TPat -- Texture pattern struct +* Intersection - intersection struct +* +* OUTPUT +* +* RETURNS +* +* DBL value in the range 0.0 to 1.0, 0.0 if normal is NULL +* +* AUTHOR +* +* Wolfgang Wieser +* +* DESCRIPTION : +* +* calculates the surface slope from surface normal vector just as normal +* slope_pattern but uses "spherical normal vector", i.e. uses the +* pattern evaluation point (EPoint) instead of the user-specified +* slope vector. +* +* CHANGES +* +******************************************************************************/ + +static DBL radial_slope_pattern (VECTOR EPoint, TPATTERN *TPat, INTERSECTION *Isection) +{ + DBL value, value1, value2; + + if (Isection == NULL) return 0.0; /* just in case ... */ + + /* Need a normalized version of the evaulation point: */ + VECTOR EP_norm; + VNormalize(EP_norm,EPoint); + /* Calculate projection of slope onto normal vector */ + VDot(value1, Isection->PNormal, EP_norm); + + /* Clamp to 1.0. */ + /* should never be necessary since both vectors are normalized */ + if (value1 > 1.0) value1 = 1.0; + else if (value1 < -1.0) value1 = -1.0; + + value1 = asin(value1) / M_PI * 2.0; + value1 = (value1 + 1.0) * 0.5; /* normalize to [0..1] interval */ + + /* Clamp to 1.0. */ + /*if ( value1 == 1.0 ) + { + value1= value1- EPSILON; + } + else + { + value1 = (value1 < 0.0) ? 1.0 + fmod(value1, 1.0) : fmod(value1, 1.0); + }*/ + return value1; /* no altitude defined */ +} + + +/***************************************************************************** +* +* FUNCTION +* * slope_pattern * * INPUT diff -urN povray-3.6.1/source/pattern.h povray-3.6.1-ww/source/pattern.h --- povray-3.6.1/source/pattern.h 2004-07-18 12:16:26.000000000 +0200 +++ povray-3.6.1-ww/source/pattern.h 2004-08-11 21:22:26.000000000 +0200 @@ -83,6 +83,7 @@ AGATE_PATTERN, GRANITE_PATTERN, GRADIENT_PATTERN, + GRID_PATTERN, /* PATTERN1_PATTERN, PATTERN2_PATTERN, PATTERN3_PATTERN,*/ @@ -111,6 +112,7 @@ DENSITY_FILE_PATTERN, FUNCTION_PATTERN, SLOPE_PATTERN, + RADIAL_SLOPE_PATTERN, PIGMENT_PATTERN, IMAGE_PATTERN }; diff -urN povray-3.6.1/source/prt_imagestore.cpp povray-3.6.1-ww/source/prt_imagestore.cpp --- povray-3.6.1/source/prt_imagestore.cpp 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_imagestore.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,129 @@ +/* + * prt_imagestore.cpp + * + * Implementing the image store for the progressive refinement tracing (PRT) + * extension. This should be replaced by a better implementation which can + * be shared among other extensions which need such a store. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#include "frame.h" +#include "render.h" +#include "renderio.h" + +#include "prt_imagestore.h" + + +BEGIN_POV_NAMESPACE + +// Color conversion factor for PRTImageStore::Pixel <-> COLOUR. +static const float col_cv_fact=65000.0f; + + +inline PRTImageStore::Pixel *PRTImageStore::_PixPtr(int x,int y) +{ + x-=xoff; + y-=yoff; + assert(x>=0 && y>=0 && x<width && y<height); + return(&data[y*width+x]); +} + + +void PRTImageStore::SetPixel(int x,int y,const COLOUR col) +{ + Pixel *p=_PixPtr(x,y); + // The test for <1.0 is needed since version 3.6.1. + p->c[0]=u_int16_t(col[pRED]<1.0 ? col[pRED]* col_cv_fact+0.5f : col_cv_fact); + p->c[1]=u_int16_t(col[pGREEN]<1.0 ? col[pGREEN]*col_cv_fact+0.5f : col_cv_fact); + p->c[2]=u_int16_t(col[pBLUE]<1.0 ? col[pBLUE]* col_cv_fact+0.5f : col_cv_fact); +} + + +void PRTImageStore::GetPixel(int x,int y,COLOUR col) +{ + Pixel *p=_PixPtr(x,y); + col[pRED]= float(p->c[0])/col_cv_fact; + col[pGREEN]=float(p->c[1])/col_cv_fact; + col[pBLUE]= float(p->c[2])/col_cv_fact; + col[pFILTER]=0.0; + col[pTRANSM]=0.0; +} + + +void PRTImageStore::SaveImageContent(int screen_width,int screen_height) +{ + // Save image: + // Allocate an image line with full screen width: + COLOUR *imgdata=(COLOUR*)POV_MALLOC( + (screen_width+1 /*<--???*/)*sizeof(COLOUR),"scan line"); + + // Make sure untraced parts get black (or should we use alpha=1.0?) + // "Backgdound" for untraced pixels: + COLOUR back_col; + Make_ColourA(back_col, 0.0, 0.0, 0.0, 0.0, 0.0); + + for(int i=0; i<screen_width; i++) + Assign_Colour(imgdata[i],back_col); + + // Write the untraced part on top of the image: + for(int y=0; y<yoff; y++) + { + Current_Line_Number=y; + output_single_image_line_with_alpha_correction(imgdata,y); + } + + // Write the traced image lines: + int xend=xoff+width; + for(int y=yoff; y<yoff+height; y++) + { + Current_Line_Number=y; + for(int x=xoff; x<xend; x++) + { GetPixel(x,y,imgdata[x]); } + output_single_image_line_with_alpha_correction(imgdata,y); + } + + // Write the untraced part on bottom of the image: + for(int i=xoff; i<xend; i++) + Assign_Colour(imgdata[i],back_col); + for(int y=yoff+height; y<screen_height; y++) + { + Current_Line_Number=y; + output_single_image_line_with_alpha_correction(imgdata,y); + } + + POV_FREE(imgdata); +} + + +PRTImageStore::PRTImageStore(int w,int h,int _xoff,int _yoff) +{ + width=w; + height=h; + xoff=_xoff; + yoff=_yoff; + + // Allocate and initialize image buffer: + size_t need_size=sizeof(Pixel)*width*height; + data=(Pixel*)POV_MALLOC(need_size,"PRT image data"); + for(size_t i=0,e=size_t(width)*height; i<e; i++) + { + data[i].c[0]=0; + data[i].c[1]=0; + data[i].c[2]=0; + } +} + + +PRTImageStore::~PRTImageStore() +{ + if(data) + { POV_FREE(data); data=NULL; } +} + +END_POV_NAMESPACE diff -urN povray-3.6.1/source/prt_imagestore.h povray-3.6.1-ww/source/prt_imagestore.h --- povray-3.6.1/source/prt_imagestore.h 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_imagestore.h 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,71 @@ +/* + * prt_imagestore.h + * + * Implementing the image store for the progressive refinement tracing (PRT) + * extension. This should be replaced by a better implementation which can + * be shared among other extensions which need such a store. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#ifndef PRT_IMAGESTORE_H +#define PRT_IMAGESTORE_H + +BEGIN_POV_NAMESPACE + +// Preliminary image store to store the rendered image before saving it. +// The image store only stores the RGB channels (and neither filter nor +// transparency) and uses 16bit intergers for storage. This is done to +// conserve memory. +class PRTImageStore +{ + private: + // Size of the image: + int width,height; + // X,Y offset to be subtracted from user coordinates: + int xoff,yoff; + + // Represents a pixel in the image data: + struct Pixel + { + u_int16_t c[3]; // red,green,blue + }; + + // Pixel data array: + Pixel *data; + + // Get Pixel pointer for coordinates: + inline Pixel *_PixPtr(int x,int y); + + public: + // w,h: size of the image to store. + // xoff,yoff: X,Y coordinate offsets (i.e. left top coos of + // the viewport). + PRTImageStore(int w,int h,int xoff,int yoff); + ~PRTImageStore(); + + // Get image width, height and number of bytes allocated to + // save the image data: + inline int Width() const { return(width); } + inline int Height() const { return(height); } + inline size_t GetBufferSize() const + { return(sizeof(Pixel)*width*height); } + + // Set pixel value at specified position: + void SetPixel(int x,int y,const COLOUR col); + + // Get pixel value at specified position: + void GetPixel(int x,int y,COLOUR col); + + // Write the entire image to output file: + void SaveImageContent(int screen_width,int screen_height); +}; + +END_POV_NAMESPACE + +#endif /* PRT_IMAGESTORE_H */ diff -urN povray-3.6.1/source/prt_render.cpp povray-3.6.1-ww/source/prt_render.cpp --- povray-3.6.1/source/prt_render.cpp 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_render.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,541 @@ +/* + * prt_render.cpp + * + * Implementing tile heap for progressive refinement tracing (PRT) extension. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#include "frame.h" +#include "povray.h" +#include "povmsend.h" +#include "vbuffer.h" +#include "prt_render.h" +#include "renderio.h" + +//-----------BEGIN FIXME SECTION---------------------------------------------- +// FIXME: The PRECISION_TIMER_AVAILABLE thingy needs fixing. +// The best way to change it would be to allow for several +// precision timers using the precision timer macros or +// even better by supplying a precision timer class. +#if PRECISION_TIMER_AVAILABLE +#include <sys/time.h> /* UNIX ONLY! */ +#endif + +// FIXME: This is used to display the PRT status information like +// rendering progress and memory usage. +#define PRT_STATUS_TEXT(fmt...) fprintf(stderr,fmt); +//-----------END FIXME SECTION------------------------------------------------ + + +BEGIN_POV_NAMESPACE + +// Initialize static data: +// See prt_render.h for more information. +PRTRenderer *PRTRenderer::renderer=NULL; +int PRTRenderer::initial_tile_size=12; +int PRTRenderer::min_tile_size=4; +int PRTRenderer::max_manual_tiles=32; +bool PRTRenderer::dont_trace_final=false; +bool PRTRenderer::plot_traced_only=false; + + +//-----------BEGIN FIXME SECTION---------------------------------------------- + +// This is the numver of color channels and is normally 5 +// (pRED,pGREEN,pBLUE,pFILTER,pTRANSM). +// It would probably be the best solution to set this somewhere in frame.h. +static const int COLOUR_CHANNELS=sizeof(COLOUR)/sizeof(COLC); + +//-----------END FIXME SECTION------------------------------------------------ + + +// Calculate bilinear interpolation of float value: +// px,py in range 0..1; px1=1-px, py1=1-py, +static inline float PRT_interpolate_bilinear( + float lt,float rt,float lb,float rb, + float px,float py,float px1,float py1) +{ + return( py * (px*rb + px1*lb) + py1 * (px*rt + px1*lt) ); +} + +// Do bilinear interpolation of COLOUR values: +static inline void PRT_interpolate_bilinear(COLOUR dest, + COLOUR lt,COLOUR rt,COLOUR lb,COLOUR rb, + float px,float py) +{ + float px1=1.0f-px; + float py1=1.0f-py; + for(unsigned int ii=0; ii<COLOUR_CHANNELS; ii++) + dest[ii]=PRT_interpolate_bilinear(lt[ii],rt[ii],lb[ii],rb[ii], + px,py,px1,py1); +} + + +// Actually trace a pixel. No check is done if the pixel was already +// traced. The pixel is traced and then marked as traced in the image +// pixel state buffer. Returns (clipped) color value of trace call. +void PRTRenderer::_DoTracePixel(int xco,int yco,COLOUR col) +{ + /* Trace current pixel. */ + if(Current_Line_Number!=yco) + { + Current_Line_Number=yco; + // I will NOT use Send_ProgressUpdate() because this function + // assumes that we're tracing line-by-line, top-to-bottom. + // Instead we use our own function here. + //Send_ProgressUpdate(PROGRESS_RENDERING); + Do_Cooperate(0); // <-- ??? + Prune_Vista_Tree(Current_Line_Number); + } + COLOUR unclippedColour; + trace_pixel(xco,yco,col,unclippedColour); + ++traced_pixels; + + // Mark pixel as traced: + istate.Set(xco,yco,PS_Traced); + + // Plot pixel on display: + plot_pixel(xco,yco,col); + + // Store pixel value: + img->SetPixel(xco,yco,col); + + // Update progress info: + if(traced_pixels*100/total_pixels != (traced_pixels-1)*100/total_pixels || + Stop_Flag) + { PRT_STATUS_TEXT( + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + "PRT: %s: %3d%% (%u / %u pixels), Tile heap: %d / %d ", + Stop_Flag ? "Abort" : "Trace", + int(traced_pixels*100/total_pixels),traced_pixels,total_pixels, + tileheap.NTiles(),tileheap.ASize()); } + + // Hack for testing: abort trace. + //if(traced_pixels==width*height*43/100) + //{ ++Stop_Flag; } + + // Forced=2 means that povray_exit() is not called even if user abort + // flag (Stop_Flag) is set, so that PRT can clean up cleanly. + Check_User_Abort(/*Forced=*/2/*special*/); +} + + +#if PRECISION_TIMER_AVAILABLE +long msec_elapsed(const struct timeval *old,const struct timeval *current) +{ + struct timeval _curr; + if(!current) + { + gettimeofday(&_curr,NULL); + current=&_curr; + } + return( + (current->tv_sec - old->tv_sec )*1000L + + (current->tv_usec - old->tv_usec)/1000L ); +} +#endif + + +// Trace all (not-yet-traced) pixels in passed box. +int PRTRenderer::_TraceEachPixelInBox(int x0,int y0,int w,int h,bool manual) +{ + #if PRECISION_TIMER_AVAILABLE + struct timeval start_tv,curr_tv; + gettimeofday(&start_tv,NULL); + #endif + + int shown_h=0; + for(int y=0; y<h; y++) + { + for(int x=0; x<w; x++) + { + _TracePixelIfNeeded(x+x0,y+y0); + if(Stop_Flag) return(-1); + + if(manual && man.new_tile) + { + POV_DISPLAY_UPDATE_RECT(opts.Preview_RefCon, + x0,y0+shown_h,w,y+1-shown_h); + return(y0+y); + } + + // Okay, this IS ugly. + #if PRECISION_TIMER_AVAILABLE + gettimeofday(&curr_tv,NULL); + if(msec_elapsed(&start_tv,&curr_tv)>300) + #else + if(x+1==w) + #endif + { + POV_DISPLAY_UPDATE_RECT(opts.Preview_RefCon, + x0,y0+shown_h,w,y+1-shown_h); + shown_h=y; + #if PRECISION_TIMER_AVAILABLE + start_tv=curr_tv; + #endif + } + } + } + + POV_DISPLAY_UPDATE_RECT(opts.Preview_RefCon, + x0,y0+shown_h,w,h+1-shown_h); + + return(y0+h); +} + + +void PRTRenderer::_InterpolateTileUsingCornerPixels(int x0,int y0,int w,int h) +{ + int rw = x0+w==xco_1 ? w-1 : w; + int rh = y0+h==yco_1 ? h-1 : h; + + // Pixels: left/right top/bottom: + COLOUR lt; img->GetPixel(x0, y0, lt); + COLOUR rt; img->GetPixel(x0+rw,y0, rt); + COLOUR lb; img->GetPixel(x0, y0+rh,lb); + COLOUR rb; img->GetPixel(x0+rw,y0+rh,rb); + + COLOUR tmp; + for(int dy=0; dy<h; dy++) + { + int yco=y0+dy; + + for(int dx=0; dx<w; dx++) + { + int xco=x0+dx; + + if(istate.Query(xco,yco)==PS_Traced) continue; + + PRT_interpolate_bilinear(/*dest=*/tmp, + lt,rt,lb,rb,float(dx)/rw,float(dy)/rh); + + // Set state to "interpolated": + istate.Set(xco,yco,PS_Interpolated); + + // Plot pixel for GUI: + if(!plot_traced_only) + { plot_pixel(xco,yco,tmp); } + + // Store pixel value: + img->SetPixel(xco,yco,tmp); + } + } + + POV_DISPLAY_UPDATE_RECT(opts.Preview_RefCon,x0,y0,w,h); +} + + +int PRTRenderer::_CalcInterest(const COLOUR *edge,int y,int w,int h) +{ + // Calculate standard deviation. + COLOUR std_dev; + float sdsum=0.0; + for(int ii=0; ii<COLOUR_CHANNELS; ii++) + { + float sum=0.0f; + float sq_sum=0.0f; + for(int e=0; e<4; e++) + { + float tmp=edge[e][ii]; + sum+=tmp; + sq_sum+=tmp*tmp; + } + float sd=sq_sum/4.0-sum*sum/16.0; + sd=sd<=0.0 ? 0.0 : sqrtf(sd); + //fprintf(stderr,"+%f< ",sd); + std_dev[ii]=sd; + sdsum+=sd; + } + + static const float sdmax=float(INT_MAX-1)/100000000.0f; + if(sdsum>=sdmax) + { + //fprintf(stderr,"PRT: OOPS: sdsum=%f >= %f\n",sdsum,sdmax); + sdsum=sdmax; + } + + float size_fact=sqrtf(float(w*h))/float(initial_tile_size); + size_fact=powf(size_fact,1.3f); // <-- critical factor (1.3) + if(size_fact<1.0f) sdsum*=size_fact; + + // Subtract y coordinate to give top-down direction a little precedence. + return(int(sdsum*100000000.0f)-y); +} + + +void PRTRenderer::_CreateTile(int x,int y,int w,int h,int mode) +{ + if(x+w>xco_1) w=xco_1-x; + if(y+h>yco_1) h=yco_1-y; + if(w<1 || h<1) return; + + int rw = x+w==xco_1 ? w-1 : w; + int rh = y+h==yco_1 ? h-1 : h; + + COLOUR edge[4]; + _TracePixelIfNeeded(x, y, edge[0]); if(Stop_Flag) return; + _TracePixelIfNeeded(x+rw,y, edge[1]); if(Stop_Flag) return; + _TracePixelIfNeeded(x, y+rh,edge[2]); if(Stop_Flag) return; + _TracePixelIfNeeded(x+rw,y+rh,edge[3]); if(Stop_Flag) return; + + int interest=_CalcInterest(edge,y,rw,rh); + + //fprintf(stderr,"AddTile(%d,%d,%d,%d, %d)\n",x,y,w,h,interest); + + if(mode>0) + { tileheap.AddTile(x,y,w,h,interest); } + else + { tileheap.ReplaceFirst(x,y,w,h,interest); } + + // Draw interpolated preview: + _InterpolateTileUsingCornerPixels(x,y,w,h); +} + + +// Process all tiles in the manual tile list. +// Be careful with the code since the user can add new manual tiles at any +// time. +// Manual tiles have precedence and get rendered in a lifo style, i.e. +// the last asdded manual tile gets renderd first. +void PRTRenderer::_ProcessManualTiles() +{ + while(man.ntiles && !Stop_Flag) + { + man.curr_tile_idx=man.ntiles-1; + man.new_tile=0; + PRTTileHeap::Tile rtile(man.tiles[man.curr_tile_idx]); + + int newy=_TraceEachPixelInBox( + rtile.x,rtile.y,rtile.w,rtile.h,/*manual=*/1); + if(newy<0) break; + + if(man.curr_tile_idx<0) continue; + assert(man.tiles[man.curr_tile_idx].x==rtile.x && + man.tiles[man.curr_tile_idx].y==rtile.y ); + + if(newy>=rtile.y+rtile.h) + { + // Tile done completely. Remove it. + --man.ntiles; + assert(man.ntiles>=man.curr_tile_idx); + memmove(man.tiles+man.curr_tile_idx,man.tiles+man.curr_tile_idx+1, + (man.ntiles-man.curr_tile_idx)*sizeof(PRTTileHeap::Tile)); + } + else + { + rtile.h-=newy-rtile.y; + rtile.y=newy; + man.tiles[man.curr_tile_idx]=rtile; + } + } +} + + +// See prt_render.h. +void PRTRenderer::ManualTraceRequest(int x,int y,int w,int h) +{ + // Clip request size to image size: + if(x<xco_0) x=xco_0; + if(y<yco_0) y=yco_0; + if(x+w>xco_1) w=xco_1-x; + if(y+h>yco_1) h=yco_1-y; + + if(!w || !h) return; + + //fprintf(stderr,"manual(%d %d %d %d)\n",x,y,w,h); + // Add manual tile entry. + PRTTileHeap::Tile *t; + if(man.ntiles>=max_manual_tiles) + { + // Remove oldest tile to make room for new one: + memmove(man.tiles,man.tiles+1, + sizeof(PRTTileHeap::Tile)*(max_manual_tiles-1)); + t=&man.tiles[man.ntiles-1]; + --man.curr_tile_idx; + } + else + { t=&man.tiles[man.ntiles++]; } + + t->x=x; + t->y=y; + t->w=w; + t->h=h; + t->interest=0; + + // Set flag: + man.new_tile=1; +} + + +// See prt_render.h. +void PRTRenderer::RenderPreview() +{ + // Cover the complete image with tiles of initial size. + // Tiles may stretch beyond image borders on the right and bottom + // which is harmless because _CreateTile() can handle this case. + for(int y=yco_0; y<yco_1; y+=initial_tile_size) + { + for(int x=xco_0; x<xco_1; x+=initial_tile_size) + { + _CreateTile(x,y,initial_tile_size,initial_tile_size,1); + if(Stop_Flag) return; + _ProcessManualTiles(); + if(Stop_Flag) return; + } + } +} + + +// See prt_render.h. +void PRTRenderer::DoRefinement() +{ + // Continuously render the most interesting tiles: + while(!Stop_Flag) + { + _ProcessManualTiles(); + if(Stop_Flag) break; + + // Get most interesting tile. We're done if none is left. + const PRTTileHeap::Tile *rtilep=tileheap.GetFirst(); + if(!rtilep) break; + + //fprintf(stderr,"[%d %d %d %d - %d]\n", + // rtilep->x,rtilep->y,rtilep->w,rtilep->h,rtilep->interest); + + // Small tiles get traced completely. Large ones get split. + if(rtilep->w<min_tile_size && rtilep->h<min_tile_size) + { + if(!dont_trace_final) + { _TraceEachPixelInBox(rtilep->x,rtilep->y,rtilep->w,rtilep->h); } + + // This tile was rendered completely and is no longer needed. + tileheap.PopFirst(); + continue; + } + + // Need a temporary because of re-alloc isues. + PRTTileHeap::Tile rtile(*rtilep); + + // Split along longer side. + if(rtile.w>rtile.h) + { + _CreateTile(rtile.x,rtile.y,rtile.w/2,rtile.h,0); + _CreateTile(rtile.x+rtile.w/2,rtile.y, + rtile.w-rtile.w/2,rtile.h,1); + } + else + { + _CreateTile(rtile.x,rtile.y,rtile.w,rtile.h/2,0); + _CreateTile(rtile.x,rtile.y+rtile.h/2, + rtile.w,rtile.h-rtile.h/2,1); + } + } + + PRT_STATUS_TEXT("\nPRT: Tile heap size: %d tiles, %d bytes\n", + tileheap.ASize(),tileheap.ASize()*sizeof(PRTTileHeap::Tile)); +} + + +void PRTRenderer::RedrawFromIData(int do_plot_traced_only) +{ + switch(do_plot_traced_only) + { + case 0: plot_traced_only=0; break; + case 1: plot_traced_only=1; break; + case -1: plot_traced_only=!plot_traced_only; break; + } + + COLOUR back_colA,back_colB; + // This is the original white background checker: + //Make_ColourA(back_colA, 1.0, 1.0, 1.0, 0.0, 0.0); + //Make_ColourA(back_colB, 0.75, 0.75, 0.75, 0.0, 0.0); + // This is a mostly black background checker: + Make_ColourA(back_colA, 0.0, 0.0, 0.0, 0.0, 0.0); + Make_ColourA(back_colB, 0.25, 0.25, 0.25, 0.0, 0.0); + + COLOUR col; + // Process the complete view port: + for(int y=yco_0; y<yco_1; y++) + { + for(int x=xco_0; x<xco_1; x++) + { + PixelState ps=istate.Query(x,y); + if(ps==PS_Traced || (ps==PS_Interpolated && !plot_traced_only)) + { + img->GetPixel(x,y,col); + plot_pixel(x,y,col); + } + else + { plot_pixel(x,y,(x/8+y/8)&1 ? back_colB : back_colA); } + } + } +} + + +PRTRenderer::PRTRenderer(int _xco_0,int _yco_0,int _xco_1,int _yco_1, + PRTImageStore *_img) : + xco_0(_xco_0),xco_1(_xco_1), + yco_0(_yco_0),yco_1(_yco_1), + width(xco_1-xco_0), + height(yco_1-yco_0), + tileheap(), + istate(width,height,xco_0,yco_0), + img(_img) +{ + // Manual tile list initialisation: + man.ntiles=0; + man.tiles=(PRTTileHeap::Tile*)POV_MALLOC( + sizeof(PRTTileHeap::Tile)*max_manual_tiles,"manual tile array"); + man.new_tile=false; + man.curr_tile_idx=-1; + + traced_pixels=0; + total_pixels=width*height; + + PRT_STATUS_TEXT("\nPRT: Image buffer: %u kb (%dx%d)\n", + (img->GetBufferSize()+512)/1024,img->Width(),img->Height()); +} + + +PRTRenderer::~PRTRenderer() +{ + if(man.tiles) + { POV_FREE(man.tiles); man.tiles=NULL; } + + img=NULL; +} + + +/******************************************************************************/ + +PRTRenderer::ImageState::ImageState(int _w,int h,int _xoff,int _yoff) +{ + w=_w; + xoff=_xoff; + yoff=_yoff; + + int n2bits=w*h; + int nwords=(n2bits+4*sizeof(unsigned int)-1)/(4*sizeof(unsigned int)); + this->data=(unsigned int*)POV_MALLOC(nwords*sizeof(unsigned int), + "PRT image pixel status"); + + // Initialize with PS_Unset: + // Alternatively, use memset(data,0,nwords*sizeof(unsigned int)); + for(int y=0; y<h; y++) + for(int x=0; x<w; x++) + Set(x+xoff,y+yoff,PS_Unset); +} + +PRTRenderer::ImageState::~ImageState() +{ + if(data) + { POV_FREE(data); data=NULL; } +} + +END_POV_NAMESPACE diff -urN povray-3.6.1/source/prt_render.h povray-3.6.1-ww/source/prt_render.h --- povray-3.6.1/source/prt_render.h 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_render.h 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,242 @@ +/* + * prt_render.h + * + * Implementing rendering/tracing/ray shooting algorithm for + * the progressive refinement tracing (PRT) extension. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#ifndef PRT_RENDER_H +#define PRT_RENDER_H + +#include "prt_tileheap.h" +#include "prt_imagestore.h" + + +BEGIN_POV_NAMESPACE + +// This class implements the PRT renderer. +// There is a (static) global pointer hook which is needed by +// the user interfaces to allow the user to manually supply regions +// to be traced. +class PRTRenderer +{ + public: + // Global pointer to PRT renderer. NULL is PRT is not active. + // See also comment above. + static PRTRenderer *renderer; + + // These are some tuning parameters. One could consider making + // them user-changeable but there is probably little need to do + // so in the most cases. + // Initially trace preview with tiles of this size (width and height). + static int initial_tile_size; + // Minimum tile size for tiles in tile heap. Smaller tiles will get + // traced completely. + static int min_tile_size; + // (Max) number of manual tile entries: + static int max_manual_tiles; + // This is for debugging, only: Set this to 1 and the final tiles + // with size<min_tile_size will NOT be traced but left interpolated. + static bool dont_trace_final; + // Set this to 1 and the interpolated pixels will not be shown + // in the POVRay window: + static bool plot_traced_only; + + private: + // Coordinates of "viewport", i.e. part of the image to be rendered: + int xco_0,xco_1; // left top corner in pixels + int yco_0,yco_1; // right+1 bottom+1 corner in pixels + // Size (of viewport): + int width,height; // width=xco_1-xco_0, etc. + + // Some statistics: + int traced_pixels; + int total_pixels; // = width*height + + // Central tile heap storing the parts of the image still + // to be rendered, sorted by interest value (most interesting + // tile first). + PRTTileHeap tileheap; + + // Manual tiles which always have precedence: + struct + { + // The mantiles array has the fixed size max_manual_tiles + // and newest entries are last. + int ntiles; + PRTTileHeap::Tile *tiles; // Array of tiles [max_manual_tiles]. + int curr_tile_idx; + bool new_tile; + } man; + + // NOTE: Larger pixel state values have precedence. + // Values must be in range 0..3. + enum PixelState + { + PS_Unset=0, + PS_Interpolated, + PS_Traced, + }; + + // Internal supplementary class which stores a 2bit information + // for each pixel in the viewport: If the pixel was not yet + // set (PS_Unset), if it was interpolated (PS_Interpolated) or + // traced (PS_Traced). + // Storage requirement is roughly width*height/4 bytes. + class ImageState + { + private: + // Image width: + int w; + + // x,y offset to be subtracted from user coos: + int xoff,yoff; + + // This stores the information for each pixel. + unsigned int *data; + + public: + // Pass width and height of the image. + // xoff and yoff are x,y offsets to be subtracted from + // the coos, i.e. left top of the viewport. + ImageState(int w,int h,int xoff=0,int yoff=0); + ~ImageState(); + + // Note: Coordinates must be in range xoff..xoff+w-1 and + // yoff..yoff+h-1 for X and Y, respectively. + // No range check is performed. + + // Query pixel state. + inline PixelState Query(int x,int y) const + { + x-=xoff; y-=yoff; + int i0=y*w+x,i1=i0/(4*sizeof(unsigned int)); + i0=(i0-i1*(4*sizeof(unsigned int)))*2; + return(PixelState((data[i1]>>i0)&3)); + } + + // Set pixel stae + inline void Set(int x,int y,PixelState ps) + { + x-=xoff; y-=yoff; + int i0=y*w+x,i1=i0/(4*sizeof(unsigned int)); + i0=(i0-i1*(4*sizeof(unsigned int)))*2; + data[i1]&=~(((unsigned int)3)<<i0); + data[i1]|=(((unsigned int)ps)<<i0); + } + } istate; + + // This is the complete image store used by the PRTRenderer: + PRTImageStore *img; + + // Actually trace a pixel. + // Never use this directly, always use _TracePixelIfNeeded(). + void _DoTracePixel(int xco,int yco,COLOUR col); + + // Trace pixel if needed and store color value in col. + // If pixel was already traced, simply return color value. + inline void _TracePixelIfNeeded(int xco,int yco,COLOUR col) + { + if(istate.Query(xco,yco)!=PS_Traced) + { _DoTracePixel(xco,yco,col); } + else + { img->GetPixel(xco,yco,col); } + } + // Similar but do not return the color value of the pixel. + inline void _TracePixelIfNeeded(int xco,int yco) + { + if(istate.Query(xco,yco)!=PS_Traced) + { COLOUR dummy; _DoTracePixel(xco,yco,dummy); } + } + + // Calc interest value for a tile which has the colors + // edge[0]..edge[3] in the 4 edges of the tile and the + // size w,h. The y coordinate is needed to give top-down + // tracing a small advantage in the interest calculation. + int _CalcInterest(const COLOUR *edge,int y,int w,int h); + + // Process all tiles in the manual tile "list": + void _ProcessManualTiles(); + + // Create a (normal) tile and add it to the tile heap. + // This involves tracing of the corner pixels (if not yet traced). + // mode: 1 -> Add tile; 0 -> replace first tile + void _CreateTile(int x,int y,int w,int h,int mode); + + // Trace all (not-yet-traced) pixels in passed box. + // Set manual flag if this was a manually specified rectangle. + // Returns new Y coordinate or -1 on abort. + int _TraceEachPixelInBox(int x0,int y0,int w,int h,bool manual=0); + + // Similar to _TraceEachPixelInBox() but bilinearly interpolate + // the pixels based on the 4 corner pixels. + // This will NOT overwrite those pixels inside the passed coordinates + // which were already traced. + void _InterpolateTileUsingCornerPixels(int x0,int y0,int w,int h); + + // Do not use these (hence they are made private): + PRTRenderer(const PRTRenderer&) : istate(0,0) {} + PRTRenderer &operator=(const PRTRenderer &) { return(*this); } + public: + // NOTE: PRTRenderer is no C++-safe class, i.e. do not assign or + // use copy-constructor. + // Pass part of the image to be rendered as arguments. + // The passed PRTImageStore is a pointer to the image store to be + // used. The image store is used to store the traced pixels in + // the image. It must provide the following interface: + // void SetPixel(int x,int y,const COLOUR col); + // void GetPixel(int x,int y,COLOUR col); + // (x,y are normal trace coordinates, i.e. in range xco_0..xco_1-1 + // and yco_0..yco_1-1, respectively) + // void SaveImageContent(<what's needed>); + // ...to write the entire image to the output file. + // int Width(); int Height(); size_t GetBufferSize() + // ...for diagnositc message (could also be left away). + PRTRenderer(int xco_0,int yco_0,int xco_1,int yco_1, + PRTImageStore *img); + ~PRTRenderer(); + + // This is called initially to render a preview of the complete image. + // It is important to do so to make sure all the pixels to be + // rendered for the complete image (or viewport) are inside + // some tile. (Pixels which are never put into a tile will never get + // traced). + void RenderPreview(); + + // After having rendered the preview, call this to have the + // tiles refined (and manual tiles rendered with precedence). + // Function returns on user quit or when the complete image + // has been rendered. + void DoRefinement(); + + // This is used by the user interface to add manual tiles to be + // traced with precedence. There are no more than max_manual_tiles + // and newer manual requests override older ones. + // The manual tiles are processed in a lifo manner, i.e. the last + // added tile is traced first. + // The coordinates are clipped to avoid out-of-range coos. + void ManualTraceRequest(int x,int y,int w,int h); + + // This function will re-plot the complete image on the user + // interface based upon the data in the image store. + // If do_plot_traced_only is set, only the traced (and not the + // interpolated) pixels are displayed. Use special value -1 + // for "toggle operation" (i.e. to invert the current value of + // the flag). + void RedrawFromIData(int do_plot_traced_only); +}; + +// Function prototype from render.cpp: +extern void trace_pixel(int x, int y, COLOUR ColourClipped, + COLOUR ColourUnclipped); + +END_POV_NAMESPACE + +#endif /* PRT_RENDERER_H */ diff -urN povray-3.6.1/source/prt_tileheap.cpp povray-3.6.1-ww/source/prt_tileheap.cpp --- povray-3.6.1/source/prt_tileheap.cpp 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_tileheap.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,115 @@ +/* + * prt_tileheap.cpp + * + * Implementing tile heap for progressive refinement tracing (PRT) extension. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#include "frame.h" +#include "prt_tileheap.h" + +BEGIN_POV_NAMESPACE + +// Move tile [idx] up in heap structure until heap condition is matched. +void PRTTileHeap::_upheap(size_t idx) +{ + heap[0].interest=INTEREST_MARK; + Tile tmp=heap[idx]; + while(heap[idx/2].interest<=tmp.interest) + { + heap[idx]=heap[idx/2]; + idx/=2; + } + heap[idx]=tmp; +} + +// Move tile [idx] down in heap structure until heap condition is matched. +void PRTTileHeap::_downheap(size_t idx) +{ + size_t j; + Tile tmp=heap[idx]; + //heap[ntiles+1].interest=INT_MIN; + while(idx<=ntiles/2) + { + j=idx+idx; + if(j<ntiles && heap[j].interest<heap[j+1].interest) ++j; + if(tmp.interest>=heap[j].interest) break; + heap[idx]=heap[j]; + idx=j; + } + heap[idx]=tmp; +} + + +// See prt_tileheap.h: +void PRTTileHeap::AddTile(int x,int y,int w,int h,int interest) +{ + if(ntiles>=asize) + { + //assert(ntiles==asize); + asize=asize ? asize*2 : 1024; + heap=(Tile*)POV_REALLOC(heap,sizeof(Tile)*(asize+2),"Tile heap"); + //fprintf(stderr,"PRT: Tile heap realloc: %u (%u kb)\n", + // asize,((asize+2)*sizeof(Tile)+512)/1024); + } + + Tile *t=&heap[++ntiles]; + t->x=x; t->y=y; + t->w=w; t->h=h; + t->interest=interest>INTEREST_MAX ? INTEREST_MAX : interest; + + _upheap(ntiles); +} + + +// See prt_tileheap.h: +void PRTTileHeap::ReplaceFirst(int x,int y,int w,int h,int interest) +{ + //assert(ntiles); + + Tile *t=&heap[1]; + t->x=x; t->y=y; + t->w=w; t->h=h; + t->interest=interest>INTEREST_MAX ? INTEREST_MAX : interest; + + _downheap(1); +} + + +// See prt_tileheap.h: +void PRTTileHeap::PopFirst() +{ + if(ntiles>1) + { + heap[1]=heap[ntiles--]; + _downheap(1); + } + else if(ntiles==1) + { + ntiles=0; + } +} + + +// Construct empty tile heap: +PRTTileHeap::PRTTileHeap() +{ + asize=2048; + ntiles=0; + heap=(Tile*)POV_MALLOC(sizeof(Tile)*(asize+2),"Tile heap"); +} + +// Cleanup tile heap: +PRTTileHeap::~PRTTileHeap() +{ + if(heap) + { POV_FREE(heap); heap=NULL; } +} + +END_POV_NAMESPACE diff -urN povray-3.6.1/source/prt_tileheap.h povray-3.6.1-ww/source/prt_tileheap.h --- povray-3.6.1/source/prt_tileheap.h 1970-01-01 01:00:00.000000000 +0100 +++ povray-3.6.1-ww/source/prt_tileheap.h 2004-08-11 21:40:47.000000000 +0200 @@ -0,0 +1,90 @@ +/* + * prt_tileheap.h + * + * Implementing tile heap for progressive refinement tracing (PRT) extension. + * + * Copytight (c) 2003--2004 by Wolfgang Wieser + * + * This file is published under the POVRay license as bundeled with + * the official POVRay distribution and available on the povray homepage + * http://www.povray.org/. + * + */ + +#ifndef PRT_TILEHEAP_H +#define PRT_TILEHEAP_H + +BEGIN_POV_NAMESPACE + +// Tile heap stores all timage tiles which shall still be rendered. +// This is part of the PRT (progressive refinement tracing) extension. +class PRTTileHeap +{ + public: + // Special mark value for head of tile; no interest value + // may be as large as this value. + static const int INTEREST_MARK=INT_MAX-1; + // Max interest value: + static const int INTEREST_MAX=INTEREST_MARK-1; + + // A tile is a region in the image. + // The 4 corners of the tile (x,y),(x+w,y),(x,y+h),(x+w,y+h) + // are always rendered. Note: In case the corners lie outside + // the view port, they are set to the last pixel inside the + // viewport, e.g. xco_1-1 instead of x+w. + struct Tile + { + // Tile size and position: + int x,y; + short int w,h; + // How "interesting" the tile is: + int interest; + }; + + private: + // Number of allocated tile entries (actually, 2 elements more + // are allocated): + size_t asize; + // Number of tiles in heap (without special first and last): + size_t ntiles; + // Heap array: NOTE: heap has entries + // heap[1]...heap[ntiles] because heap[0] and heap[ntiles+1] + // are special. + Tile *heap; + + // Upheap/downheap don't need explanation :) + void _upheap(size_t idx); + void _downheap(size_t idx); + + // Do not use these (hence they are made private): + PRTTileHeap(const PRTTileHeap&) {} + PRTTileHeap &operator=(const PRTTileHeap &) { return(*this); } + public: + // NOTE: PRTTileHeap is no C++-safe class, i.e. do not assign or + // use copy-constructor. + PRTTileHeap(); + ~PRTTileHeap(); + + // Get alloc size and number of tiles in the heap: + inline size_t ASize() const { return(asize); } + inline size_t NTiles() const { return(ntiles); } + + // Add a tile entry to the heap. + // Pass coordinates and interest value. + // (No check for overlapping tiles is performed here.) + void AddTile(int x,int y,int w,int h,int interest); + + // Get most interesting tile: + inline const Tile *GetFirst() + { return(ntiles ? &heap[1] : NULL); } + + // Remove first tile: + void PopFirst(); + + // Replace first tile with passed one: + void ReplaceFirst(int x,int y,int w,int h,int interest); +}; + +END_POV_NAMESPACE + +#endif /* PRT_TILEHEAP_H */ diff -urN povray-3.6.1/source/rendctrl.cpp povray-3.6.1-ww/source/rendctrl.cpp --- povray-3.6.1/source/rendctrl.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/rendctrl.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -515,6 +515,9 @@ case 2: Start_Adaptive_Tracing(); break; + case 4: + Start_Progressive_Refinement_Tracing(); + break; case 1: default: Start_Non_Adaptive_Tracing(); diff -urN povray-3.6.1/source/render.cpp povray-3.6.1-ww/source/render.cpp --- povray-3.6.1/source/render.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/render.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -69,7 +69,9 @@ #include "matrices.h" #include "pov_util.h" #include "povms.h" -#include "pov_util.h" + +#include "prt_render.h" + BEGIN_POV_NAMESPACE @@ -787,7 +789,7 @@ void Check_User_Abort(int Forced) { - if(Forced) + if(Forced==1) Stop_Flag=true; else { @@ -800,7 +802,7 @@ } } - if(Stop_Flag == true) + if(Stop_Flag == true && Forced!=2) povray_exit(2); } @@ -1674,12 +1676,100 @@ for (Sib = ((CSG *)parent)->Children; Sib != NULL; Sib = Sib->Sibling) { if(IsObjectInCSG(Object, Sib)) - found = true; + { found = true; break; } } } return found; } + +/***************************************************************************** +* +* FUNCTION +* +* Start_Progressive_Refinement_Tracing +* +* INPUT +* +* OUTPUT +* +* RETURNS +* +* AUTHOR +* +* Wolfgang Wieser based on Start_Non_Adaptive_Tracing() from the POV-Team. +* +* DESCRIPTION +* +* The functionality is like Start_Non_Adaptive_Tracing() but instead of +* tracing pixels row-by-row, left-to-right, it first traces the edge points +* of (normally 16x16) tiles and then refines these tiles. Each tile gets +* an "interest value" which is effectively the standard deviation of the +* color values of the tile edges. Tiles with higher interest values are +* traced earlier. +* +* CHANGES +* +* Written 07/2004 by Wolfgang Wieser when porting the 3.5 patch to +* POVRay-3.6. +* +******************************************************************************/ + +void Start_Progressive_Refinement_Tracing() +{ + /* Field rendering is not supported by PRT. + * Field rendering would introduce unneeded complexity and is not + * likely to be used in the design phase anyways. */ + if(opts.FrameSeq.Field_Render_Flag) + { + Error("Cannot use field rendering with PRT."); + } + /* Anti-aliasing cannot be used together with PRT. */ + if((opts.Options & ANTIALIAS)) + { + Error("Cannot use anti-aliasing with PRT."); + } + + /* Set jitterscale. */ + JitterScale = opts.JitterScale / (DBL)opts.AntialiasDepth; + + /* Create image store to save the image content: */ + PRTImageStore istore( + /*w=*/opts.Last_Column-opts.First_Column, + /*h=*/opts.Last_Line-opts.First_Line, + /*xoff=*/opts.First_Column, + /*yoff=*/opts.First_Line); + + /* Create PRT renderer: */ + PRTRenderer prt_renderer( + opts.First_Column,opts.First_Line, + opts.Last_Column,opts.Last_Line, + &istore); + /* This is a global pointer used by the user interfaces to access the + * PRT renderer: */ + PRTRenderer::renderer=&prt_renderer; + + /* First, trace a preview: + * This is needed to feed the tile heap with tiles covering the complete + * image to render. If we skip this, nothing will effectively be rendered. */ + prt_renderer.RenderPreview(); + + /* Now, perform the progressive refinement step by continuously + * refining the most interesting tiles: */ + prt_renderer.DoRefinement(); + + /* Done. */ + PRTRenderer::renderer=NULL; + + /* Finally, save the rendered image. We also come here in case of + * user abort which is just what is intended. */ + istore.SaveImageContent(Frame.Screen_Width,Frame.Screen_Height); + + /* Now, we'll exit if the user aborted the trace. */ + Check_User_Abort(false); +} + + /***************************************************************************** * * FUNCTION diff -urN povray-3.6.1/source/render.h povray-3.6.1-ww/source/render.h --- povray-3.6.1/source/render.h 2004-07-18 12:16:26.000000000 +0200 +++ povray-3.6.1-ww/source/render.h 2004-08-11 21:40:47.000000000 +0200 @@ -94,6 +94,7 @@ void Start_Tracing_Mosaic_Preview (int StartPixelSize, int EndPixelSize); void Start_Adaptive_Tracing (void); void Start_Non_Adaptive_Tracing (void); +void Start_Progressive_Refinement_Tracing (void); void Initialize_Renderer (void); void Terminate_Renderer (void); DBL Trace (RAY *Ray, COLOUR Colour, DBL Weight); diff -urN povray-3.6.1/source/tokenize.cpp povray-3.6.1-ww/source/tokenize.cpp --- povray-3.6.1/source/tokenize.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/tokenize.cpp 2004-08-11 21:22:26.000000000 +0200 @@ -365,6 +365,7 @@ {GRAY_TOKEN, "gray"}, {GRAY_THRESHOLD_TOKEN, "gray_threshold" }, {GREEN_TOKEN, "green"}, + {GRID_PATTERN_TOKEN, "grid_pattern" }, {HASH_TOKEN, "#"}, {HAT_TOKEN, "^"}, {HEIGHT_FIELD_TOKEN, "height_field"}, @@ -526,6 +527,7 @@ {QUICK_COLOUR_TOKEN, "quick_colour"}, {QUILTED_TOKEN, "quilted"}, {RADIAL_TOKEN, "radial"}, + {RADIAL_SLOPE_TOKEN,"radial_slope"}, {RADIANS_TOKEN, "radians"}, {RADIOSITY_TOKEN, "radiosity" }, {RADIUS_TOKEN, "radius"}, diff -urN povray-3.6.1/source/userdisp.cpp povray-3.6.1-ww/source/userdisp.cpp --- povray-3.6.1/source/userdisp.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/source/userdisp.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -161,4 +161,10 @@ } } +/****************************************************************************/ +void POV_Std_Display_Update_Rect (int x,int y,int w,int h) +{ + /* Nothing to do */ +} + END_POV_NAMESPACE diff -urN povray-3.6.1/source/userdisp.h povray-3.6.1-ww/source/userdisp.h --- povray-3.6.1/source/userdisp.h 2004-07-18 12:16:27.000000000 +0200 +++ povray-3.6.1-ww/source/userdisp.h 2004-08-11 21:40:47.000000000 +0200 @@ -66,6 +66,7 @@ void POV_Std_Display_Plot (int x, int y, unsigned int r, unsigned int g, unsigned int b, unsigned int a); void POV_Std_Display_Plot_Rect (int x1, int y1, int x2, int y2, unsigned int r, unsigned int g, unsigned int b, unsigned int a); void POV_Std_Display_Plot_Box (int x1,int y1,int x2,int y2, unsigned int r,unsigned int g,unsigned int b,unsigned int a); +void POV_Std_Display_Update_Rect (int x,int y,int w,int h); END_POV_NAMESPACE diff -urN povray-3.6.1/unix/config.h povray-3.6.1-ww/unix/config.h --- povray-3.6.1/unix/config.h 2004-07-18 12:16:27.000000000 +0200 +++ povray-3.6.1-ww/unix/config.h 2004-08-11 21:40:47.000000000 +0200 @@ -159,9 +159,9 @@ /* * POVMS stuff. */ -#define POVRAY_BEGIN_COOPERATE if(setjmp(globalSetJmpEnv) == 0) { -#define POVRAY_END_COOPERATE } -#define EXIT_POVRAY(n) longjmp(globalSetJmpEnv, 1) +#define POVRAY_BEGIN_COOPERATE int _rv=setjmp(globalSetJmpEnv); if(_rv==0) { +#define POVRAY_END_COOPERATE } else if(_rv!=1) throw (_rv-1000000); +#define EXIT_POVRAY(n) longjmp(globalSetJmpEnv, n ? (n+1000000) : 1) /* * Namespace. @@ -230,6 +230,9 @@ #define POV_DISPLAY_PLOT_BOX(ref,x1,y1,x2,y2,r,g,b,a) \ UNIX_display_plot_box((x1),(y1),(x2),(y2),(r),(g),(b),(a)) +#define POV_DISPLAY_UPDATE_RECT(ref,x1,y1,w,h) \ + UNIX_display_update_rect((x1),(y1),(w),(h)) + /**************************************************************************** * Variables diff -urN povray-3.6.1/unix/svga.cpp povray-3.6.1-ww/unix/svga.cpp --- povray-3.6.1/unix/svga.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/unix/svga.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -556,6 +556,35 @@ /***************************************************************************** * +* FUNCTION SVGA_display_update_rect +* +* INPUT +* +* OUTPUT +* +* RETURNS +* +* AUTHOR Wolfgang Wieser +* +* DESCRIPTION +* +* Update specified rectangle by re-drawing it on the screen; this is +* a no-op for SVGA mode. +* +* CHANGES +* +* Jul 2004: Creation +* +******************************************************************************/ + +void SVGA_display_update_rect(int x, int y, int w, int h) +{ + /* Nothing to do IMHO. */ +} + + +/***************************************************************************** +* * FUNCTION SVGA_display_finished * * INPUT status diff -urN povray-3.6.1/unix/svga.h povray-3.6.1-ww/unix/svga.h --- povray-3.6.1/unix/svga.h 2004-07-18 12:16:27.000000000 +0200 +++ povray-3.6.1-ww/unix/svga.h 2004-08-11 21:40:47.000000000 +0200 @@ -47,6 +47,7 @@ void SVGA_display_plot_box (int x1, int y1, int x2, int y2, unsigned int Red, unsigned int Green, unsigned int Blue, unsigned int Alpha); +void SVGA_display_update_rect(int x, int y, int w, int h); void SVGA_display_finished (void); void SVGA_display_close (void); int SVGA_test_abort (void); diff -urN povray-3.6.1/unix/unix.cpp povray-3.6.1-ww/unix/unix.cpp --- povray-3.6.1/unix/unix.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/unix/unix.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -219,6 +219,7 @@ void (*UNIX_display_plot_box) (int x1, int y1, int x2, int y2, unsigned int Red, unsigned int Green, unsigned int Blue, unsigned int Alpha); +void (*UNIX_display_update_rect) (int x1, int y1, int w, int h); void (*UNIX_display_finished) (void); void (*UNIX_display_close) (void); int (*UNIX_test_abort) (void); @@ -2297,6 +2298,7 @@ UNIX_display_plot = &POV_Std_Display_Plot; UNIX_display_plot_rect = &POV_Std_Display_Plot_Rect; UNIX_display_plot_box = &POV_Std_Display_Plot_Box; + UNIX_display_update_rect=&POV_Std_Display_Update_Rect; UNIX_display_finished = &POV_Std_Display_Finished; UNIX_display_close = &POV_Std_Display_Close; UNIX_test_abort = &POV_Std_Test_Abort; @@ -2398,6 +2400,7 @@ UNIX_display_plot = &POV_Std_Display_Plot; UNIX_display_plot_rect = &POV_Std_Display_Plot_Rect; UNIX_display_plot_box = &POV_Std_Display_Plot_Box; + UNIX_display_update_rect=&POV_Std_Display_Update_Rect; UNIX_display_finished = &POV_Std_Display_Finished; UNIX_display_close = &POV_Std_Display_Close; UNIX_test_abort = &POV_Std_Test_Abort; @@ -2417,6 +2420,7 @@ UNIX_display_plot = &XWIN_display_plot; UNIX_display_plot_rect = &XWIN_display_plot_rect; UNIX_display_plot_box = &XWIN_display_plot_box; + UNIX_display_update_rect=&XWIN_display_update_rect; UNIX_display_finished = &XWIN_display_finished; UNIX_display_close = &XWIN_display_close; UNIX_test_abort = &XWIN_test_abort; @@ -2437,6 +2441,7 @@ UNIX_display_plot = &SVGA_display_plot; UNIX_display_plot_rect = &SVGA_display_plot_rect; UNIX_display_plot_box = &SVGA_display_plot_box; + UNIX_display_update_rect=&SVGA_display_update_rect; UNIX_display_finished = &SVGA_display_finished; UNIX_display_close = &SVGA_display_close; UNIX_test_abort = &SVGA_test_abort; diff -urN povray-3.6.1/unix/unix.h povray-3.6.1-ww/unix/unix.h --- povray-3.6.1/unix/unix.h 2004-07-18 12:16:27.000000000 +0200 +++ povray-3.6.1-ww/unix/unix.h 2004-08-11 21:40:47.000000000 +0200 @@ -92,6 +92,7 @@ extern void (*UNIX_display_plot_box) (int x1, int y1, int x2, int y2, unsigned int Red, unsigned int Green, unsigned int Blue, unsigned int Alpha); +extern void (*UNIX_display_update_rect)(int x,int y,int w,int h); extern void (*UNIX_display_finished) (void); extern void (*UNIX_display_close) (void); extern int (*UNIX_test_abort) (void); diff -urN povray-3.6.1/unix/xwin.cpp povray-3.6.1-ww/unix/xwin.cpp --- povray-3.6.1/unix/xwin.cpp 2004-08-11 21:04:31.000000000 +0200 +++ povray-3.6.1-ww/unix/xwin.cpp 2004-08-11 21:40:47.000000000 +0200 @@ -160,6 +160,8 @@ #include "xwin.h" #include "unix.h" /* For string manipulation functions */ +#include "prt_render.h" + USING_POV_NAMESPACE USING_POV_BASE_NAMESPACE @@ -199,7 +201,8 @@ ButtonReleaseMask | \ KeyPressMask | \ ExposureMask | \ - StructureNotifyMask) + StructureNotifyMask | \ + Button1MotionMask | Button2MotionMask | Button3MotionMask) #define theRED 0 #define theGREEN 1 @@ -295,6 +298,16 @@ static IMAGE *theBackground = NULL; #endif +/* PRT mouse tracking state: */ +static struct +{ + int curr_size; // Currently used manual tile size. + int last_x,last_y; // x,y center of last manual tile +} prt_state={ + 0, + 0,0 +}; + /***************************************************************************** * Global variables @@ -1981,6 +1994,38 @@ /***************************************************************************** * +* FUNCTION XWIN_display_update_rect +* +* INPUT +* +* OUTPUT +* +* RETURNS +* +* AUTHOR Wolfgang Wieser +* +* DESCRIPTION +* +* Simply update the specified rectangle by re-drawing it on the screen +* based on the data in the the current XImage image data store. +* +* CHANGES +* +* Jul 2004: Creation +* +******************************************************************************/ + +void XWIN_display_update_rect(int x, int y, int w, int h) +{ + if(!theDisplay) return; + + XPutImage(theDisplay, theWindow, theGC, theImage, x, y, x, y, w, h); + //XFlush(theDisplay); +} + + +/***************************************************************************** +* * FUNCTION XWIN_display_finished * * INPUT @@ -2216,7 +2261,7 @@ Debug_Info("KeyPress\n"); #endif theKeySym = XKeycodeToKeysym(theDisplay, theEvent.xkey.keycode, 0); - if ((opts.Options & EXITENABLE || finished) + if ((opts.Options & EXITENABLE || finished || PRTRenderer::renderer) && (theKeySym == XK_Q || theKeySym == XK_q)) { abortRender = true; @@ -2228,6 +2273,11 @@ refresh_y_min = 0; refresh_y_max = Frame.Screen_Height; } + else if(theKeySym == XK_t && PRTRenderer::renderer) + { + PRTRenderer::renderer->RedrawFromIData( + /*do_plot_traced_only=*/-1/*toggle*/); + } else { refresh_y_min = theCurrY; @@ -2243,26 +2293,62 @@ #endif if (!finished) // [WW] bugfix { - /* - * If not finished, a button click will cause a window refresh. - */ - refresh_x_min = 0; - refresh_y_min = theCurrY; - refresh_x_max = Frame.Screen_Width; - refresh_y_max = theCurrY + 1; - // [WW] moved abortRender to the new ButtonRelease event below - refresh = true; + if(PRTRenderer::renderer) + { + switch(theEvent.xbutton.button) + { + case 1: prt_state.curr_size=16; break; + case 2: prt_state.curr_size=32; break; + case 3: prt_state.curr_size=64; break; + default: prt_state.curr_size=64; break; + } + prt_state.last_x=theEvent.xmotion.x; + prt_state.last_y=theEvent.xmotion.y; + PRTRenderer::renderer->ManualTraceRequest( + theEvent.xmotion.x-prt_state.curr_size/2, + theEvent.xmotion.y-prt_state.curr_size/2, + prt_state.curr_size,prt_state.curr_size); + } + else + { + /* + * If not finished, a button click will cause a window refresh. + */ + refresh_x_min = 0; + refresh_y_min = theCurrY; + refresh_x_max = Frame.Screen_Width; + refresh_y_max = theCurrY + 1; + // [WW] moved abortRender to the new ButtonRelease event below + refresh = true; + } } break; case ButtonRelease: // [WW] bugfix: added this event #if (X11_DEBUG > 0) Debug_Info("ButtonRelease\n"); #endif - if(finished) + if(finished && !prt_state.curr_size) { /* If finished, a button release will quit. */ abortRender |= finished; } + else + { prt_state.curr_size=0; } + break; + case MotionNotify: + if(PRTRenderer::renderer && prt_state.curr_size) + { + if(abs(prt_state.last_x-theEvent.xmotion.x)>prt_state.curr_size/2 || + abs(prt_state.last_y-theEvent.xmotion.y)>prt_state.curr_size/2 ) + { + prt_state.last_x=theEvent.xmotion.x; + prt_state.last_y=theEvent.xmotion.y; + PRTRenderer::renderer->ManualTraceRequest( + theEvent.xmotion.x-prt_state.curr_size/2, + theEvent.xmotion.y-prt_state.curr_size/2, + prt_state.curr_size,prt_state.curr_size); + } + } break; case ClientMessage: /* @@ -2279,7 +2365,8 @@ if (theEvent.xclient.message_type == WM_PROTOCOLS && theEvent.xclient.data.l[0] == WM_DELETE_WINDOW) { - if(opts.Options & EXITENABLE) // [WW] abort rendering if +x set + if((opts.Options & EXITENABLE) // [WW] abort rendering if +x set + || PRTRenderer::renderer) abortRender = true; refresh = false; diff -urN povray-3.6.1/unix/xwin.h povray-3.6.1-ww/unix/xwin.h --- povray-3.6.1/unix/xwin.h 2004-07-18 12:16:27.000000000 +0200 +++ povray-3.6.1-ww/unix/xwin.h 2004-08-11 21:40:47.000000000 +0200 @@ -47,6 +47,7 @@ void XWIN_display_plot_box (int x1, int y1, int x2, int y2, unsigned int Red, unsigned int Green, unsigned int Blue, unsigned int Alpha); +void XWIN_display_update_rect(int x, int y, int w, int h); void XWIN_display_finished (void); void XWIN_display_close (void); int XWIN_test_abort (void);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor