diff -ur  povray-3.6.1/source/fpmetric.cpp  povray-3.6.1-ww/source/fpmetric.cpp
---  povray-3.6.1/source/fpmetric.cpp	2004-07-01 20:01:44.000000000 +0200
+++  povray-3.6.1-ww/source/fpmetric.cpp	2004-07-10 10:02:41.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 -ur  povray-3.6.1/source/isosurf.cpp  povray-3.6.1-ww/source/isosurf.cpp
---  povray-3.6.1/source/isosurf.cpp	2004-07-01 20:01:44.000000000 +0200
+++  povray-3.6.1-ww/source/isosurf.cpp	2004-07-04 22:12:35.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 -ur  povray-3.6.1/source/pattern.cpp  povray-3.6.1-ww/source/pattern.cpp
---  povray-3.6.1/source/pattern.cpp	2004-07-01 20:01:46.000000000 +0200
+++  povray-3.6.1-ww/source/pattern.cpp	2004-07-03 13:11:30.000000000 +0200
@@ -3317,7 +3317,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);
diff -ur  povray-3.6.1/source/render.cpp  povray-3.6.1-ww/source/render.cpp
---  povray-3.6.1/source/render.cpp	2004-07-01 20:01:48.000000000 +0200
+++  povray-3.6.1-ww/source/render.cpp	2004-07-03 13:04:04.000000000 +0200
@@ -1674,7 +1674,7 @@
     for (Sib = ((CSG *)parent)->Children; Sib != NULL; Sib = Sib->Sibling)
     {
       if(IsObjectInCSG(Object, Sib))
-        found = true;
+      {  found = true;  break;  }
     }
   }
   return found;
diff -ur  povray-3.6.1/source/lighting.cpp  povray-3.6.1-ww/source/lighting.cpp
---  povray-3.6.1/source/lighting.cpp	2004-07-10 23:25:14.000000000 +0200
+++  povray-3.6.1-ww/source/lighting.cpp	2004-07-25 12:29:33.435001600 +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/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);

