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