xref: /aosp_15_r20/external/mesa3d/src/mesa/math/m_eval.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker 
2*61046927SAndroid Build Coastguard Worker /*
3*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
15*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker /*
28*61046927SAndroid Build Coastguard Worker  * eval.c was written by
29*61046927SAndroid Build Coastguard Worker  * Bernd Barsuhn ([email protected]) and
30*61046927SAndroid Build Coastguard Worker  * Volker Weiss ([email protected]).
31*61046927SAndroid Build Coastguard Worker  *
32*61046927SAndroid Build Coastguard Worker  * My original implementation of evaluators was simplistic and didn't
33*61046927SAndroid Build Coastguard Worker  * compute surface normal vectors properly.  Bernd and Volker applied
34*61046927SAndroid Build Coastguard Worker  * used more sophisticated methods to get better results.
35*61046927SAndroid Build Coastguard Worker  *
36*61046927SAndroid Build Coastguard Worker  * Thanks guys!
37*61046927SAndroid Build Coastguard Worker  */
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
41*61046927SAndroid Build Coastguard Worker #include "main/config.h"
42*61046927SAndroid Build Coastguard Worker #include "m_eval.h"
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker static GLfloat inv_tab[MAX_EVAL_ORDER];
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker /*
49*61046927SAndroid Build Coastguard Worker  * Horner scheme for Bezier curves
50*61046927SAndroid Build Coastguard Worker  *
51*61046927SAndroid Build Coastguard Worker  * Bezier curves can be computed via a Horner scheme.
52*61046927SAndroid Build Coastguard Worker  * Horner is numerically less stable than the de Casteljau
53*61046927SAndroid Build Coastguard Worker  * algorithm, but it is faster. For curves of degree n
54*61046927SAndroid Build Coastguard Worker  * the complexity of Horner is O(n) and de Casteljau is O(n^2).
55*61046927SAndroid Build Coastguard Worker  * Since stability is not important for displaying curve
56*61046927SAndroid Build Coastguard Worker  * points I decided to use the Horner scheme.
57*61046927SAndroid Build Coastguard Worker  *
58*61046927SAndroid Build Coastguard Worker  * A cubic Bezier curve with control points b0, b1, b2, b3 can be
59*61046927SAndroid Build Coastguard Worker  * written as
60*61046927SAndroid Build Coastguard Worker  *
61*61046927SAndroid Build Coastguard Worker  *        (([3]        [3]     )     [3]       )     [3]
62*61046927SAndroid Build Coastguard Worker  * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
63*61046927SAndroid Build Coastguard Worker  *
64*61046927SAndroid Build Coastguard Worker  *                                           [n]
65*61046927SAndroid Build Coastguard Worker  * where s=1-t and the binomial coefficients [i]. These can
66*61046927SAndroid Build Coastguard Worker  * be computed iteratively using the identity:
67*61046927SAndroid Build Coastguard Worker  *
68*61046927SAndroid Build Coastguard Worker  * [n]               [n  ]             [n]
69*61046927SAndroid Build Coastguard Worker  * [i] = (n-i+1)/i * [i-1]     and     [0] = 1
70*61046927SAndroid Build Coastguard Worker  */
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker void
_math_horner_bezier_curve(const GLfloat * cp,GLfloat * out,GLfloat t,GLuint dim,GLuint order)74*61046927SAndroid Build Coastguard Worker _math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t,
75*61046927SAndroid Build Coastguard Worker 			  GLuint dim, GLuint order)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker    GLfloat s, powert, bincoeff;
78*61046927SAndroid Build Coastguard Worker    GLuint i, k;
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    if (order >= 2) {
81*61046927SAndroid Build Coastguard Worker       bincoeff = (GLfloat) (order - 1);
82*61046927SAndroid Build Coastguard Worker       s = 1.0F - t;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker       for (k = 0; k < dim; k++)
85*61046927SAndroid Build Coastguard Worker 	 out[k] = s * cp[k] + bincoeff * t * cp[dim + k];
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker       for (i = 2, cp += 2 * dim, powert = t * t; i < order;
88*61046927SAndroid Build Coastguard Worker 	   i++, powert *= t, cp += dim) {
89*61046927SAndroid Build Coastguard Worker 	 bincoeff *= (GLfloat) (order - i);
90*61046927SAndroid Build Coastguard Worker 	 bincoeff *= inv_tab[i];
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker 	 for (k = 0; k < dim; k++)
93*61046927SAndroid Build Coastguard Worker 	    out[k] = s * out[k] + bincoeff * powert * cp[k];
94*61046927SAndroid Build Coastguard Worker       }
95*61046927SAndroid Build Coastguard Worker    }
96*61046927SAndroid Build Coastguard Worker    else {			/* order=1 -> constant curve */
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker       for (k = 0; k < dim; k++)
99*61046927SAndroid Build Coastguard Worker 	 out[k] = cp[k];
100*61046927SAndroid Build Coastguard Worker    }
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker /*
104*61046927SAndroid Build Coastguard Worker  * Tensor product Bezier surfaces
105*61046927SAndroid Build Coastguard Worker  *
106*61046927SAndroid Build Coastguard Worker  * Again the Horner scheme is used to compute a point on a
107*61046927SAndroid Build Coastguard Worker  * TP Bezier surface. First a control polygon for a curve
108*61046927SAndroid Build Coastguard Worker  * on the surface in one parameter direction is computed,
109*61046927SAndroid Build Coastguard Worker  * then the point on the curve for the other parameter
110*61046927SAndroid Build Coastguard Worker  * direction is evaluated.
111*61046927SAndroid Build Coastguard Worker  *
112*61046927SAndroid Build Coastguard Worker  * To store the curve control polygon additional storage
113*61046927SAndroid Build Coastguard Worker  * for max(uorder,vorder) points is needed in the
114*61046927SAndroid Build Coastguard Worker  * control net cn.
115*61046927SAndroid Build Coastguard Worker  */
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker void
_math_horner_bezier_surf(GLfloat * cn,GLfloat * out,GLfloat u,GLfloat v,GLuint dim,GLuint uorder,GLuint vorder)118*61046927SAndroid Build Coastguard Worker _math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v,
119*61046927SAndroid Build Coastguard Worker 			 GLuint dim, GLuint uorder, GLuint vorder)
120*61046927SAndroid Build Coastguard Worker {
121*61046927SAndroid Build Coastguard Worker    GLfloat *cp = cn + uorder * vorder * dim;
122*61046927SAndroid Build Coastguard Worker    GLuint i, uinc = vorder * dim;
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    if (vorder > uorder) {
125*61046927SAndroid Build Coastguard Worker       if (uorder >= 2) {
126*61046927SAndroid Build Coastguard Worker 	 GLfloat s, poweru, bincoeff;
127*61046927SAndroid Build Coastguard Worker 	 GLuint j, k;
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker 	 /* Compute the control polygon for the surface-curve in u-direction */
130*61046927SAndroid Build Coastguard Worker 	 for (j = 0; j < vorder; j++) {
131*61046927SAndroid Build Coastguard Worker 	    GLfloat *ucp = &cn[j * dim];
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker 	    /* Each control point is the point for parameter u on a */
134*61046927SAndroid Build Coastguard Worker 	    /* curve defined by the control polygons in u-direction */
135*61046927SAndroid Build Coastguard Worker 	    bincoeff = (GLfloat) (uorder - 1);
136*61046927SAndroid Build Coastguard Worker 	    s = 1.0F - u;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker 	    for (k = 0; k < dim; k++)
139*61046927SAndroid Build Coastguard Worker 	       cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k];
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker 	    for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder;
142*61046927SAndroid Build Coastguard Worker 		 i++, poweru *= u, ucp += uinc) {
143*61046927SAndroid Build Coastguard Worker 	       bincoeff *= (GLfloat) (uorder - i);
144*61046927SAndroid Build Coastguard Worker 	       bincoeff *= inv_tab[i];
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker 	       for (k = 0; k < dim; k++)
147*61046927SAndroid Build Coastguard Worker 		  cp[j * dim + k] =
148*61046927SAndroid Build Coastguard Worker 		     s * cp[j * dim + k] + bincoeff * poweru * ucp[k];
149*61046927SAndroid Build Coastguard Worker 	    }
150*61046927SAndroid Build Coastguard Worker 	 }
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker 	 /* Evaluate curve point in v */
153*61046927SAndroid Build Coastguard Worker 	 _math_horner_bezier_curve(cp, out, v, dim, vorder);
154*61046927SAndroid Build Coastguard Worker       }
155*61046927SAndroid Build Coastguard Worker       else			/* uorder=1 -> cn defines a curve in v */
156*61046927SAndroid Build Coastguard Worker 	 _math_horner_bezier_curve(cn, out, v, dim, vorder);
157*61046927SAndroid Build Coastguard Worker    }
158*61046927SAndroid Build Coastguard Worker    else {			/* vorder <= uorder */
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker       if (vorder > 1) {
161*61046927SAndroid Build Coastguard Worker 	 GLuint i;
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker 	 /* Compute the control polygon for the surface-curve in u-direction */
164*61046927SAndroid Build Coastguard Worker 	 for (i = 0; i < uorder; i++, cn += uinc) {
165*61046927SAndroid Build Coastguard Worker 	    /* For constant i all cn[i][j] (j=0..vorder) are located */
166*61046927SAndroid Build Coastguard Worker 	    /* on consecutive memory locations, so we can use        */
167*61046927SAndroid Build Coastguard Worker 	    /* horner_bezier_curve to compute the control points     */
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker 	    _math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder);
170*61046927SAndroid Build Coastguard Worker 	 }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker 	 /* Evaluate curve point in u */
173*61046927SAndroid Build Coastguard Worker 	 _math_horner_bezier_curve(cp, out, u, dim, uorder);
174*61046927SAndroid Build Coastguard Worker       }
175*61046927SAndroid Build Coastguard Worker       else			/* vorder=1 -> cn defines a curve in u */
176*61046927SAndroid Build Coastguard Worker 	 _math_horner_bezier_curve(cn, out, u, dim, uorder);
177*61046927SAndroid Build Coastguard Worker    }
178*61046927SAndroid Build Coastguard Worker }
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker /*
181*61046927SAndroid Build Coastguard Worker  * The direct de Casteljau algorithm is used when a point on the
182*61046927SAndroid Build Coastguard Worker  * surface and the tangent directions spanning the tangent plane
183*61046927SAndroid Build Coastguard Worker  * should be computed (this is needed to compute normals to the
184*61046927SAndroid Build Coastguard Worker  * surface). In this case the de Casteljau algorithm approach is
185*61046927SAndroid Build Coastguard Worker  * nicer because a point and the partial derivatives can be computed
186*61046927SAndroid Build Coastguard Worker  * at the same time. To get the correct tangent length du and dv
187*61046927SAndroid Build Coastguard Worker  * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
188*61046927SAndroid Build Coastguard Worker  * Since only the directions are needed, this scaling step is omitted.
189*61046927SAndroid Build Coastguard Worker  *
190*61046927SAndroid Build Coastguard Worker  * De Casteljau needs additional storage for uorder*vorder
191*61046927SAndroid Build Coastguard Worker  * values in the control net cn.
192*61046927SAndroid Build Coastguard Worker  */
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker void
_math_de_casteljau_surf(GLfloat * cn,GLfloat * out,GLfloat * du,GLfloat * dv,GLfloat u,GLfloat v,GLuint dim,GLuint uorder,GLuint vorder)195*61046927SAndroid Build Coastguard Worker _math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du,
196*61046927SAndroid Build Coastguard Worker 			GLfloat * dv, GLfloat u, GLfloat v, GLuint dim,
197*61046927SAndroid Build Coastguard Worker 			GLuint uorder, GLuint vorder)
198*61046927SAndroid Build Coastguard Worker {
199*61046927SAndroid Build Coastguard Worker    GLfloat *dcn = cn + uorder * vorder * dim;
200*61046927SAndroid Build Coastguard Worker    GLfloat us = 1.0F - u, vs = 1.0F - v;
201*61046927SAndroid Build Coastguard Worker    GLuint h, i, j, k;
202*61046927SAndroid Build Coastguard Worker    GLuint minorder = uorder < vorder ? uorder : vorder;
203*61046927SAndroid Build Coastguard Worker    GLuint uinc = vorder * dim;
204*61046927SAndroid Build Coastguard Worker    GLuint dcuinc = vorder;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    /* Each component is evaluated separately to save buffer space  */
207*61046927SAndroid Build Coastguard Worker    /* This does not drasticaly decrease the performance of the     */
208*61046927SAndroid Build Coastguard Worker    /* algorithm. If additional storage for (uorder-1)*(vorder-1)   */
209*61046927SAndroid Build Coastguard Worker    /* points would be available, the components could be accessed  */
210*61046927SAndroid Build Coastguard Worker    /* in the innermost loop which could lead to less cache misses. */
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker #define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
213*61046927SAndroid Build Coastguard Worker #define DCN(I, J) dcn[(I)*dcuinc+(J)]
214*61046927SAndroid Build Coastguard Worker    if (minorder < 3) {
215*61046927SAndroid Build Coastguard Worker       if (uorder == vorder) {
216*61046927SAndroid Build Coastguard Worker 	 for (k = 0; k < dim; k++) {
217*61046927SAndroid Build Coastguard Worker 	    /* Derivative direction in u */
218*61046927SAndroid Build Coastguard Worker 	    du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) +
219*61046927SAndroid Build Coastguard Worker 	       v * (CN(1, 1, k) - CN(0, 1, k));
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker 	    /* Derivative direction in v */
222*61046927SAndroid Build Coastguard Worker 	    dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) +
223*61046927SAndroid Build Coastguard Worker 	       u * (CN(1, 1, k) - CN(1, 0, k));
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker 	    /* bilinear de Casteljau step */
226*61046927SAndroid Build Coastguard Worker 	    out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) +
227*61046927SAndroid Build Coastguard Worker 	       u * (vs * CN(1, 0, k) + v * CN(1, 1, k));
228*61046927SAndroid Build Coastguard Worker 	 }
229*61046927SAndroid Build Coastguard Worker       }
230*61046927SAndroid Build Coastguard Worker       else if (minorder == uorder) {
231*61046927SAndroid Build Coastguard Worker 	 for (k = 0; k < dim; k++) {
232*61046927SAndroid Build Coastguard Worker 	    /* bilinear de Casteljau step */
233*61046927SAndroid Build Coastguard Worker 	    DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k);
234*61046927SAndroid Build Coastguard Worker 	    DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k);
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker 	    for (j = 0; j < vorder - 1; j++) {
237*61046927SAndroid Build Coastguard Worker 	       /* for the derivative in u */
238*61046927SAndroid Build Coastguard Worker 	       DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k);
239*61046927SAndroid Build Coastguard Worker 	       DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker 	       /* for the `point' */
242*61046927SAndroid Build Coastguard Worker 	       DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k);
243*61046927SAndroid Build Coastguard Worker 	       DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
244*61046927SAndroid Build Coastguard Worker 	    }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker 	    /* remaining linear de Casteljau steps until the second last step */
247*61046927SAndroid Build Coastguard Worker 	    for (h = minorder; h < vorder - 1; h++)
248*61046927SAndroid Build Coastguard Worker 	       for (j = 0; j < vorder - h; j++) {
249*61046927SAndroid Build Coastguard Worker 		  /* for the derivative in u */
250*61046927SAndroid Build Coastguard Worker 		  DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker 		  /* for the `point' */
253*61046927SAndroid Build Coastguard Worker 		  DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
254*61046927SAndroid Build Coastguard Worker 	       }
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker 	    /* derivative direction in v */
257*61046927SAndroid Build Coastguard Worker 	    dv[k] = DCN(0, 1) - DCN(0, 0);
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker 	    /* derivative direction in u */
260*61046927SAndroid Build Coastguard Worker 	    du[k] = vs * DCN(1, 0) + v * DCN(1, 1);
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker 	    /* last linear de Casteljau step */
263*61046927SAndroid Build Coastguard Worker 	    out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
264*61046927SAndroid Build Coastguard Worker 	 }
265*61046927SAndroid Build Coastguard Worker       }
266*61046927SAndroid Build Coastguard Worker       else {			/* minorder == vorder */
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker 	 for (k = 0; k < dim; k++) {
269*61046927SAndroid Build Coastguard Worker 	    /* bilinear de Casteljau step */
270*61046927SAndroid Build Coastguard Worker 	    DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k);
271*61046927SAndroid Build Coastguard Worker 	    DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k);
272*61046927SAndroid Build Coastguard Worker 	    for (i = 0; i < uorder - 1; i++) {
273*61046927SAndroid Build Coastguard Worker 	       /* for the derivative in v */
274*61046927SAndroid Build Coastguard Worker 	       DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k);
275*61046927SAndroid Build Coastguard Worker 	       DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker 	       /* for the `point' */
278*61046927SAndroid Build Coastguard Worker 	       DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k);
279*61046927SAndroid Build Coastguard Worker 	       DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
280*61046927SAndroid Build Coastguard Worker 	    }
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker 	    /* remaining linear de Casteljau steps until the second last step */
283*61046927SAndroid Build Coastguard Worker 	    for (h = minorder; h < uorder - 1; h++)
284*61046927SAndroid Build Coastguard Worker 	       for (i = 0; i < uorder - h; i++) {
285*61046927SAndroid Build Coastguard Worker 		  /* for the derivative in v */
286*61046927SAndroid Build Coastguard Worker 		  DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker 		  /* for the `point' */
289*61046927SAndroid Build Coastguard Worker 		  DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
290*61046927SAndroid Build Coastguard Worker 	       }
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker 	    /* derivative direction in u */
293*61046927SAndroid Build Coastguard Worker 	    du[k] = DCN(1, 0) - DCN(0, 0);
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker 	    /* derivative direction in v */
296*61046927SAndroid Build Coastguard Worker 	    dv[k] = us * DCN(0, 1) + u * DCN(1, 1);
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker 	    /* last linear de Casteljau step */
299*61046927SAndroid Build Coastguard Worker 	    out[k] = us * DCN(0, 0) + u * DCN(1, 0);
300*61046927SAndroid Build Coastguard Worker 	 }
301*61046927SAndroid Build Coastguard Worker       }
302*61046927SAndroid Build Coastguard Worker    }
303*61046927SAndroid Build Coastguard Worker    else if (uorder == vorder) {
304*61046927SAndroid Build Coastguard Worker       for (k = 0; k < dim; k++) {
305*61046927SAndroid Build Coastguard Worker 	 /* first bilinear de Casteljau step */
306*61046927SAndroid Build Coastguard Worker 	 for (i = 0; i < uorder - 1; i++) {
307*61046927SAndroid Build Coastguard Worker 	    DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
308*61046927SAndroid Build Coastguard Worker 	    for (j = 0; j < vorder - 1; j++) {
309*61046927SAndroid Build Coastguard Worker 	       DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
310*61046927SAndroid Build Coastguard Worker 	       DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
311*61046927SAndroid Build Coastguard Worker 	    }
312*61046927SAndroid Build Coastguard Worker 	 }
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker 	 /* remaining bilinear de Casteljau steps until the second last step */
315*61046927SAndroid Build Coastguard Worker 	 for (h = 2; h < minorder - 1; h++)
316*61046927SAndroid Build Coastguard Worker 	    for (i = 0; i < uorder - h; i++) {
317*61046927SAndroid Build Coastguard Worker 	       DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
318*61046927SAndroid Build Coastguard Worker 	       for (j = 0; j < vorder - h; j++) {
319*61046927SAndroid Build Coastguard Worker 		  DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
320*61046927SAndroid Build Coastguard Worker 		  DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
321*61046927SAndroid Build Coastguard Worker 	       }
322*61046927SAndroid Build Coastguard Worker 	    }
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in u */
325*61046927SAndroid Build Coastguard Worker 	 du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1));
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in v */
328*61046927SAndroid Build Coastguard Worker 	 dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0));
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker 	 /* last bilinear de Casteljau step */
331*61046927SAndroid Build Coastguard Worker 	 out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) +
332*61046927SAndroid Build Coastguard Worker 	    u * (vs * DCN(1, 0) + v * DCN(1, 1));
333*61046927SAndroid Build Coastguard Worker       }
334*61046927SAndroid Build Coastguard Worker    }
335*61046927SAndroid Build Coastguard Worker    else if (minorder == uorder) {
336*61046927SAndroid Build Coastguard Worker       for (k = 0; k < dim; k++) {
337*61046927SAndroid Build Coastguard Worker 	 /* first bilinear de Casteljau step */
338*61046927SAndroid Build Coastguard Worker 	 for (i = 0; i < uorder - 1; i++) {
339*61046927SAndroid Build Coastguard Worker 	    DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
340*61046927SAndroid Build Coastguard Worker 	    for (j = 0; j < vorder - 1; j++) {
341*61046927SAndroid Build Coastguard Worker 	       DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
342*61046927SAndroid Build Coastguard Worker 	       DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
343*61046927SAndroid Build Coastguard Worker 	    }
344*61046927SAndroid Build Coastguard Worker 	 }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker 	 /* remaining bilinear de Casteljau steps until the second last step */
347*61046927SAndroid Build Coastguard Worker 	 for (h = 2; h < minorder - 1; h++)
348*61046927SAndroid Build Coastguard Worker 	    for (i = 0; i < uorder - h; i++) {
349*61046927SAndroid Build Coastguard Worker 	       DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
350*61046927SAndroid Build Coastguard Worker 	       for (j = 0; j < vorder - h; j++) {
351*61046927SAndroid Build Coastguard Worker 		  DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
352*61046927SAndroid Build Coastguard Worker 		  DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
353*61046927SAndroid Build Coastguard Worker 	       }
354*61046927SAndroid Build Coastguard Worker 	    }
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker 	 /* last bilinear de Casteljau step */
357*61046927SAndroid Build Coastguard Worker 	 DCN(2, 0) = DCN(1, 0) - DCN(0, 0);
358*61046927SAndroid Build Coastguard Worker 	 DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0);
359*61046927SAndroid Build Coastguard Worker 	 for (j = 0; j < vorder - 1; j++) {
360*61046927SAndroid Build Coastguard Worker 	    /* for the derivative in u */
361*61046927SAndroid Build Coastguard Worker 	    DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1);
362*61046927SAndroid Build Coastguard Worker 	    DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker 	    /* for the `point' */
365*61046927SAndroid Build Coastguard Worker 	    DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1);
366*61046927SAndroid Build Coastguard Worker 	    DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
367*61046927SAndroid Build Coastguard Worker 	 }
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker 	 /* remaining linear de Casteljau steps until the second last step */
370*61046927SAndroid Build Coastguard Worker 	 for (h = minorder; h < vorder - 1; h++)
371*61046927SAndroid Build Coastguard Worker 	    for (j = 0; j < vorder - h; j++) {
372*61046927SAndroid Build Coastguard Worker 	       /* for the derivative in u */
373*61046927SAndroid Build Coastguard Worker 	       DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker 	       /* for the `point' */
376*61046927SAndroid Build Coastguard Worker 	       DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
377*61046927SAndroid Build Coastguard Worker 	    }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in v */
380*61046927SAndroid Build Coastguard Worker 	 dv[k] = DCN(0, 1) - DCN(0, 0);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in u */
383*61046927SAndroid Build Coastguard Worker 	 du[k] = vs * DCN(2, 0) + v * DCN(2, 1);
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker 	 /* last linear de Casteljau step */
386*61046927SAndroid Build Coastguard Worker 	 out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
387*61046927SAndroid Build Coastguard Worker       }
388*61046927SAndroid Build Coastguard Worker    }
389*61046927SAndroid Build Coastguard Worker    else {			/* minorder == vorder */
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker       for (k = 0; k < dim; k++) {
392*61046927SAndroid Build Coastguard Worker 	 /* first bilinear de Casteljau step */
393*61046927SAndroid Build Coastguard Worker 	 for (i = 0; i < uorder - 1; i++) {
394*61046927SAndroid Build Coastguard Worker 	    DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
395*61046927SAndroid Build Coastguard Worker 	    for (j = 0; j < vorder - 1; j++) {
396*61046927SAndroid Build Coastguard Worker 	       DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
397*61046927SAndroid Build Coastguard Worker 	       DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
398*61046927SAndroid Build Coastguard Worker 	    }
399*61046927SAndroid Build Coastguard Worker 	 }
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker 	 /* remaining bilinear de Casteljau steps until the second last step */
402*61046927SAndroid Build Coastguard Worker 	 for (h = 2; h < minorder - 1; h++)
403*61046927SAndroid Build Coastguard Worker 	    for (i = 0; i < uorder - h; i++) {
404*61046927SAndroid Build Coastguard Worker 	       DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
405*61046927SAndroid Build Coastguard Worker 	       for (j = 0; j < vorder - h; j++) {
406*61046927SAndroid Build Coastguard Worker 		  DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
407*61046927SAndroid Build Coastguard Worker 		  DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
408*61046927SAndroid Build Coastguard Worker 	       }
409*61046927SAndroid Build Coastguard Worker 	    }
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker 	 /* last bilinear de Casteljau step */
412*61046927SAndroid Build Coastguard Worker 	 DCN(0, 2) = DCN(0, 1) - DCN(0, 0);
413*61046927SAndroid Build Coastguard Worker 	 DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1);
414*61046927SAndroid Build Coastguard Worker 	 for (i = 0; i < uorder - 1; i++) {
415*61046927SAndroid Build Coastguard Worker 	    /* for the derivative in v */
416*61046927SAndroid Build Coastguard Worker 	    DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0);
417*61046927SAndroid Build Coastguard Worker 	    DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker 	    /* for the `point' */
420*61046927SAndroid Build Coastguard Worker 	    DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1);
421*61046927SAndroid Build Coastguard Worker 	    DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
422*61046927SAndroid Build Coastguard Worker 	 }
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker 	 /* remaining linear de Casteljau steps until the second last step */
425*61046927SAndroid Build Coastguard Worker 	 for (h = minorder; h < uorder - 1; h++)
426*61046927SAndroid Build Coastguard Worker 	    for (i = 0; i < uorder - h; i++) {
427*61046927SAndroid Build Coastguard Worker 	       /* for the derivative in v */
428*61046927SAndroid Build Coastguard Worker 	       DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker 	       /* for the `point' */
431*61046927SAndroid Build Coastguard Worker 	       DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
432*61046927SAndroid Build Coastguard Worker 	    }
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in u */
435*61046927SAndroid Build Coastguard Worker 	 du[k] = DCN(1, 0) - DCN(0, 0);
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker 	 /* derivative direction in v */
438*61046927SAndroid Build Coastguard Worker 	 dv[k] = us * DCN(0, 2) + u * DCN(1, 2);
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker 	 /* last linear de Casteljau step */
441*61046927SAndroid Build Coastguard Worker 	 out[k] = us * DCN(0, 0) + u * DCN(1, 0);
442*61046927SAndroid Build Coastguard Worker       }
443*61046927SAndroid Build Coastguard Worker    }
444*61046927SAndroid Build Coastguard Worker #undef DCN
445*61046927SAndroid Build Coastguard Worker #undef CN
446*61046927SAndroid Build Coastguard Worker }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker /*
450*61046927SAndroid Build Coastguard Worker  * Do one-time initialization for evaluators.
451*61046927SAndroid Build Coastguard Worker  */
452*61046927SAndroid Build Coastguard Worker void
_math_init_eval(void)453*61046927SAndroid Build Coastguard Worker _math_init_eval(void)
454*61046927SAndroid Build Coastguard Worker {
455*61046927SAndroid Build Coastguard Worker    GLuint i;
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker    /* KW: precompute 1/x for useful x.
458*61046927SAndroid Build Coastguard Worker     */
459*61046927SAndroid Build Coastguard Worker    for (i = 1; i < MAX_EVAL_ORDER; i++)
460*61046927SAndroid Build Coastguard Worker       inv_tab[i] = 1.0F / i;
461*61046927SAndroid Build Coastguard Worker }
462