From b2987354f10ef5e5f495b9b9b36849749bcebec0 Mon Sep 17 00:00:00 2001
From: divverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Sun, 22 Mar 2009 19:51:44 +0000
Subject: [PATCH] change names of functions, and add comments.

The code is mathematically correct now, I added a proof of the missing link:
quadratic spline area = exactly 2/3 * area of the control points triangle!

The actual subdivisions stayed invariant, just the names of the functions make
more sense now.


git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8821 d7cf8633-e32d-0410-b094-e92efae38249
---
 curves.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/curves.c b/curves.c
index ea18cf47..ad5bb63f 100644
--- a/curves.c
+++ b/curves.c
@@ -156,7 +156,7 @@ static int Q3PatchTesselation(float largestsquared2xcurvearea, float tolerance)
 		// maps [4..8[ to 4
 }
 
-float Squared2xCurveArea(const float *a, const float *control, const float *b, int components)
+float Squared3xCurveArea(const float *a, const float *control, const float *b, int components)
 {
 #if 0
 	// mimicing the old behaviour with the new code...
@@ -178,6 +178,13 @@ float Squared2xCurveArea(const float *a, const float *control, const float *b, i
 	// but as this is hard to calculate, let's calculate an upper bound of it:
 	// the area of the triangle a->control->b->a.
 	//
+	// one can prove that the area of a quadratic spline = 2/3 * the area of
+	// the triangle of its control points!
+	// to do it, first prove it for the spline through (0,0), (1,1), (2,0)
+	// (which is a parabola) and then note that moving the control point
+	// left/right is just shearing and keeps the area of both the spline and
+	// the triangle invariant.
+	//
 	// why are we going for the spline area anyway?
 	// we know that:
 	//
@@ -186,6 +193,8 @@ float Squared2xCurveArea(const float *a, const float *control, const float *b, i
 	//
 	//   also, on circle-like or parabola-like curves, you easily get that the
 	//   double amount of line approximation segments reduces the error to its quarter
+	//   (also, easy to prove for splines by doing it for one specific one, and using
+	//   affine transforms to get all other splines)
 	//
 	// so...
 	//
@@ -214,7 +223,8 @@ float Squared2xCurveArea(const float *a, const float *control, const float *b, i
 		bb += xb * xb;
 	}
 	// area is 0.5 * sqrt(aa*bb - ab*ab)
-	// 2x area is sqrt(aa*bb - ab*ab)
+	// 2x TRIANGLE area is sqrt(aa*bb - ab*ab)
+	// 3x CURVE area is sqrt(aa*bb - ab*ab)
 	return aa * bb - ab * ab;
 #endif
 }
@@ -231,7 +241,7 @@ int Q3PatchTesselationOnX(int patchwidth, int patchheight, int components, const
 		for (x = 0;x < patchwidth-1;x += 2)
 		{
 			patch = in + ((y * patchwidth) + x) * components;
-			squared2xcurvearea = Squared2xCurveArea(&patch[0], &patch[components], &patch[2*components], components);
+			squared2xcurvearea = Squared3xCurveArea(&patch[0], &patch[components], &patch[2*components], components);
 			if (largestsquared2xcurvearea < squared2xcurvearea)
 				largestsquared2xcurvearea = squared2xcurvearea;
 		}
@@ -251,7 +261,7 @@ int Q3PatchTesselationOnY(int patchwidth, int patchheight, int components, const
 		for (x = 0;x < patchwidth;x++)
 		{
 			patch = in + ((y * patchwidth) + x) * components;
-			squared2xcurvearea = Squared2xCurveArea(&patch[0], &patch[patchwidth*components], &patch[2*patchwidth*components], components);
+			squared2xcurvearea = Squared3xCurveArea(&patch[0], &patch[patchwidth*components], &patch[2*patchwidth*components], components);
 			if (largestsquared2xcurvearea < squared2xcurvearea)
 				largestsquared2xcurvearea = squared2xcurvearea;
 		}
-- 
2.39.5