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