17117f1b4Smrg 27117f1b4Smrg/* 37117f1b4Smrg * Mesa 3-D graphics library 47117f1b4Smrg * 57117f1b4Smrg * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 247117f1b4Smrg */ 257117f1b4Smrg 267117f1b4Smrg 277117f1b4Smrg/* 287117f1b4Smrg * eval.c was written by 297117f1b4Smrg * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and 307117f1b4Smrg * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de). 317117f1b4Smrg * 327117f1b4Smrg * My original implementation of evaluators was simplistic and didn't 337117f1b4Smrg * compute surface normal vectors properly. Bernd and Volker applied 347117f1b4Smrg * used more sophisticated methods to get better results. 357117f1b4Smrg * 367117f1b4Smrg * Thanks guys! 377117f1b4Smrg */ 387117f1b4Smrg 397117f1b4Smrg 40c1f859d4Smrg#include "main/glheader.h" 41c1f859d4Smrg#include "main/config.h" 427117f1b4Smrg#include "m_eval.h" 437117f1b4Smrg 447117f1b4Smrgstatic GLfloat inv_tab[MAX_EVAL_ORDER]; 457117f1b4Smrg 467117f1b4Smrg 477117f1b4Smrg 487117f1b4Smrg/* 497117f1b4Smrg * Horner scheme for Bezier curves 507117f1b4Smrg * 517117f1b4Smrg * Bezier curves can be computed via a Horner scheme. 527117f1b4Smrg * Horner is numerically less stable than the de Casteljau 537117f1b4Smrg * algorithm, but it is faster. For curves of degree n 547117f1b4Smrg * the complexity of Horner is O(n) and de Casteljau is O(n^2). 557117f1b4Smrg * Since stability is not important for displaying curve 567117f1b4Smrg * points I decided to use the Horner scheme. 577117f1b4Smrg * 587117f1b4Smrg * A cubic Bezier curve with control points b0, b1, b2, b3 can be 597117f1b4Smrg * written as 607117f1b4Smrg * 617117f1b4Smrg * (([3] [3] ) [3] ) [3] 627117f1b4Smrg * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 637117f1b4Smrg * 647117f1b4Smrg * [n] 657117f1b4Smrg * where s=1-t and the binomial coefficients [i]. These can 667117f1b4Smrg * be computed iteratively using the identity: 677117f1b4Smrg * 687117f1b4Smrg * [n] [n ] [n] 697117f1b4Smrg * [i] = (n-i+1)/i * [i-1] and [0] = 1 707117f1b4Smrg */ 717117f1b4Smrg 727117f1b4Smrg 737117f1b4Smrgvoid 747117f1b4Smrg_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t, 757117f1b4Smrg GLuint dim, GLuint order) 767117f1b4Smrg{ 777117f1b4Smrg GLfloat s, powert, bincoeff; 787117f1b4Smrg GLuint i, k; 797117f1b4Smrg 807117f1b4Smrg if (order >= 2) { 817117f1b4Smrg bincoeff = (GLfloat) (order - 1); 827117f1b4Smrg s = 1.0F - t; 837117f1b4Smrg 847117f1b4Smrg for (k = 0; k < dim; k++) 857117f1b4Smrg out[k] = s * cp[k] + bincoeff * t * cp[dim + k]; 867117f1b4Smrg 877117f1b4Smrg for (i = 2, cp += 2 * dim, powert = t * t; i < order; 887117f1b4Smrg i++, powert *= t, cp += dim) { 897117f1b4Smrg bincoeff *= (GLfloat) (order - i); 907117f1b4Smrg bincoeff *= inv_tab[i]; 917117f1b4Smrg 927117f1b4Smrg for (k = 0; k < dim; k++) 937117f1b4Smrg out[k] = s * out[k] + bincoeff * powert * cp[k]; 947117f1b4Smrg } 957117f1b4Smrg } 967117f1b4Smrg else { /* order=1 -> constant curve */ 977117f1b4Smrg 987117f1b4Smrg for (k = 0; k < dim; k++) 997117f1b4Smrg out[k] = cp[k]; 1007117f1b4Smrg } 1017117f1b4Smrg} 1027117f1b4Smrg 1037117f1b4Smrg/* 1047117f1b4Smrg * Tensor product Bezier surfaces 1057117f1b4Smrg * 1067117f1b4Smrg * Again the Horner scheme is used to compute a point on a 1077117f1b4Smrg * TP Bezier surface. First a control polygon for a curve 1087117f1b4Smrg * on the surface in one parameter direction is computed, 1097117f1b4Smrg * then the point on the curve for the other parameter 1107117f1b4Smrg * direction is evaluated. 1117117f1b4Smrg * 1127117f1b4Smrg * To store the curve control polygon additional storage 1137117f1b4Smrg * for max(uorder,vorder) points is needed in the 1147117f1b4Smrg * control net cn. 1157117f1b4Smrg */ 1167117f1b4Smrg 1177117f1b4Smrgvoid 1187117f1b4Smrg_math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v, 1197117f1b4Smrg GLuint dim, GLuint uorder, GLuint vorder) 1207117f1b4Smrg{ 1217117f1b4Smrg GLfloat *cp = cn + uorder * vorder * dim; 1227117f1b4Smrg GLuint i, uinc = vorder * dim; 1237117f1b4Smrg 1247117f1b4Smrg if (vorder > uorder) { 1257117f1b4Smrg if (uorder >= 2) { 1267117f1b4Smrg GLfloat s, poweru, bincoeff; 1277117f1b4Smrg GLuint j, k; 1287117f1b4Smrg 1297117f1b4Smrg /* Compute the control polygon for the surface-curve in u-direction */ 1307117f1b4Smrg for (j = 0; j < vorder; j++) { 1317117f1b4Smrg GLfloat *ucp = &cn[j * dim]; 1327117f1b4Smrg 1337117f1b4Smrg /* Each control point is the point for parameter u on a */ 1347117f1b4Smrg /* curve defined by the control polygons in u-direction */ 1357117f1b4Smrg bincoeff = (GLfloat) (uorder - 1); 1367117f1b4Smrg s = 1.0F - u; 1377117f1b4Smrg 1387117f1b4Smrg for (k = 0; k < dim; k++) 1397117f1b4Smrg cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k]; 1407117f1b4Smrg 1417117f1b4Smrg for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder; 1427117f1b4Smrg i++, poweru *= u, ucp += uinc) { 1437117f1b4Smrg bincoeff *= (GLfloat) (uorder - i); 1447117f1b4Smrg bincoeff *= inv_tab[i]; 1457117f1b4Smrg 1467117f1b4Smrg for (k = 0; k < dim; k++) 1477117f1b4Smrg cp[j * dim + k] = 1487117f1b4Smrg s * cp[j * dim + k] + bincoeff * poweru * ucp[k]; 1497117f1b4Smrg } 1507117f1b4Smrg } 1517117f1b4Smrg 1527117f1b4Smrg /* Evaluate curve point in v */ 1537117f1b4Smrg _math_horner_bezier_curve(cp, out, v, dim, vorder); 1547117f1b4Smrg } 1557117f1b4Smrg else /* uorder=1 -> cn defines a curve in v */ 1567117f1b4Smrg _math_horner_bezier_curve(cn, out, v, dim, vorder); 1577117f1b4Smrg } 1587117f1b4Smrg else { /* vorder <= uorder */ 1597117f1b4Smrg 1607117f1b4Smrg if (vorder > 1) { 1617117f1b4Smrg GLuint i; 1627117f1b4Smrg 1637117f1b4Smrg /* Compute the control polygon for the surface-curve in u-direction */ 1647117f1b4Smrg for (i = 0; i < uorder; i++, cn += uinc) { 1657117f1b4Smrg /* For constant i all cn[i][j] (j=0..vorder) are located */ 1667117f1b4Smrg /* on consecutive memory locations, so we can use */ 1677117f1b4Smrg /* horner_bezier_curve to compute the control points */ 1687117f1b4Smrg 1697117f1b4Smrg _math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder); 1707117f1b4Smrg } 1717117f1b4Smrg 1727117f1b4Smrg /* Evaluate curve point in u */ 1737117f1b4Smrg _math_horner_bezier_curve(cp, out, u, dim, uorder); 1747117f1b4Smrg } 1757117f1b4Smrg else /* vorder=1 -> cn defines a curve in u */ 1767117f1b4Smrg _math_horner_bezier_curve(cn, out, u, dim, uorder); 1777117f1b4Smrg } 1787117f1b4Smrg} 1797117f1b4Smrg 1807117f1b4Smrg/* 1817117f1b4Smrg * The direct de Casteljau algorithm is used when a point on the 1827117f1b4Smrg * surface and the tangent directions spanning the tangent plane 1837117f1b4Smrg * should be computed (this is needed to compute normals to the 1847117f1b4Smrg * surface). In this case the de Casteljau algorithm approach is 1857117f1b4Smrg * nicer because a point and the partial derivatives can be computed 1867117f1b4Smrg * at the same time. To get the correct tangent length du and dv 1877117f1b4Smrg * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. 1887117f1b4Smrg * Since only the directions are needed, this scaling step is omitted. 1897117f1b4Smrg * 1907117f1b4Smrg * De Casteljau needs additional storage for uorder*vorder 1917117f1b4Smrg * values in the control net cn. 1927117f1b4Smrg */ 1937117f1b4Smrg 1947117f1b4Smrgvoid 1957117f1b4Smrg_math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du, 1967117f1b4Smrg GLfloat * dv, GLfloat u, GLfloat v, GLuint dim, 1977117f1b4Smrg GLuint uorder, GLuint vorder) 1987117f1b4Smrg{ 1997117f1b4Smrg GLfloat *dcn = cn + uorder * vorder * dim; 2007117f1b4Smrg GLfloat us = 1.0F - u, vs = 1.0F - v; 2017117f1b4Smrg GLuint h, i, j, k; 2027117f1b4Smrg GLuint minorder = uorder < vorder ? uorder : vorder; 2037117f1b4Smrg GLuint uinc = vorder * dim; 2047117f1b4Smrg GLuint dcuinc = vorder; 2057117f1b4Smrg 2067117f1b4Smrg /* Each component is evaluated separately to save buffer space */ 2077117f1b4Smrg /* This does not drasticaly decrease the performance of the */ 2087117f1b4Smrg /* algorithm. If additional storage for (uorder-1)*(vorder-1) */ 2097117f1b4Smrg /* points would be available, the components could be accessed */ 2107117f1b4Smrg /* in the innermost loop which could lead to less cache misses. */ 2117117f1b4Smrg 2127117f1b4Smrg#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)] 2137117f1b4Smrg#define DCN(I, J) dcn[(I)*dcuinc+(J)] 2147117f1b4Smrg if (minorder < 3) { 2157117f1b4Smrg if (uorder == vorder) { 2167117f1b4Smrg for (k = 0; k < dim; k++) { 2177117f1b4Smrg /* Derivative direction in u */ 2187117f1b4Smrg du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) + 2197117f1b4Smrg v * (CN(1, 1, k) - CN(0, 1, k)); 2207117f1b4Smrg 2217117f1b4Smrg /* Derivative direction in v */ 2227117f1b4Smrg dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) + 2237117f1b4Smrg u * (CN(1, 1, k) - CN(1, 0, k)); 2247117f1b4Smrg 2257117f1b4Smrg /* bilinear de Casteljau step */ 2267117f1b4Smrg out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) + 2277117f1b4Smrg u * (vs * CN(1, 0, k) + v * CN(1, 1, k)); 2287117f1b4Smrg } 2297117f1b4Smrg } 2307117f1b4Smrg else if (minorder == uorder) { 2317117f1b4Smrg for (k = 0; k < dim; k++) { 2327117f1b4Smrg /* bilinear de Casteljau step */ 2337117f1b4Smrg DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k); 2347117f1b4Smrg DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k); 2357117f1b4Smrg 2367117f1b4Smrg for (j = 0; j < vorder - 1; j++) { 2377117f1b4Smrg /* for the derivative in u */ 2387117f1b4Smrg DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k); 2397117f1b4Smrg DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); 2407117f1b4Smrg 2417117f1b4Smrg /* for the `point' */ 2427117f1b4Smrg DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k); 2437117f1b4Smrg DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); 2447117f1b4Smrg } 2457117f1b4Smrg 2467117f1b4Smrg /* remaining linear de Casteljau steps until the second last step */ 2477117f1b4Smrg for (h = minorder; h < vorder - 1; h++) 2487117f1b4Smrg for (j = 0; j < vorder - h; j++) { 2497117f1b4Smrg /* for the derivative in u */ 2507117f1b4Smrg DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); 2517117f1b4Smrg 2527117f1b4Smrg /* for the `point' */ 2537117f1b4Smrg DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); 2547117f1b4Smrg } 2557117f1b4Smrg 2567117f1b4Smrg /* derivative direction in v */ 2577117f1b4Smrg dv[k] = DCN(0, 1) - DCN(0, 0); 2587117f1b4Smrg 2597117f1b4Smrg /* derivative direction in u */ 2607117f1b4Smrg du[k] = vs * DCN(1, 0) + v * DCN(1, 1); 2617117f1b4Smrg 2627117f1b4Smrg /* last linear de Casteljau step */ 2637117f1b4Smrg out[k] = vs * DCN(0, 0) + v * DCN(0, 1); 2647117f1b4Smrg } 2657117f1b4Smrg } 2667117f1b4Smrg else { /* minorder == vorder */ 2677117f1b4Smrg 2687117f1b4Smrg for (k = 0; k < dim; k++) { 2697117f1b4Smrg /* bilinear de Casteljau step */ 2707117f1b4Smrg DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k); 2717117f1b4Smrg DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k); 2727117f1b4Smrg for (i = 0; i < uorder - 1; i++) { 2737117f1b4Smrg /* for the derivative in v */ 2747117f1b4Smrg DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k); 2757117f1b4Smrg DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); 2767117f1b4Smrg 2777117f1b4Smrg /* for the `point' */ 2787117f1b4Smrg DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k); 2797117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 2807117f1b4Smrg } 2817117f1b4Smrg 2827117f1b4Smrg /* remaining linear de Casteljau steps until the second last step */ 2837117f1b4Smrg for (h = minorder; h < uorder - 1; h++) 2847117f1b4Smrg for (i = 0; i < uorder - h; i++) { 2857117f1b4Smrg /* for the derivative in v */ 2867117f1b4Smrg DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); 2877117f1b4Smrg 2887117f1b4Smrg /* for the `point' */ 2897117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 2907117f1b4Smrg } 2917117f1b4Smrg 2927117f1b4Smrg /* derivative direction in u */ 2937117f1b4Smrg du[k] = DCN(1, 0) - DCN(0, 0); 2947117f1b4Smrg 2957117f1b4Smrg /* derivative direction in v */ 2967117f1b4Smrg dv[k] = us * DCN(0, 1) + u * DCN(1, 1); 2977117f1b4Smrg 2987117f1b4Smrg /* last linear de Casteljau step */ 2997117f1b4Smrg out[k] = us * DCN(0, 0) + u * DCN(1, 0); 3007117f1b4Smrg } 3017117f1b4Smrg } 3027117f1b4Smrg } 3037117f1b4Smrg else if (uorder == vorder) { 3047117f1b4Smrg for (k = 0; k < dim; k++) { 3057117f1b4Smrg /* first bilinear de Casteljau step */ 3067117f1b4Smrg for (i = 0; i < uorder - 1; i++) { 3077117f1b4Smrg DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); 3087117f1b4Smrg for (j = 0; j < vorder - 1; j++) { 3097117f1b4Smrg DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); 3107117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 3117117f1b4Smrg } 3127117f1b4Smrg } 3137117f1b4Smrg 3147117f1b4Smrg /* remaining bilinear de Casteljau steps until the second last step */ 3157117f1b4Smrg for (h = 2; h < minorder - 1; h++) 3167117f1b4Smrg for (i = 0; i < uorder - h; i++) { 3177117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 3187117f1b4Smrg for (j = 0; j < vorder - h; j++) { 3197117f1b4Smrg DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); 3207117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 3217117f1b4Smrg } 3227117f1b4Smrg } 3237117f1b4Smrg 3247117f1b4Smrg /* derivative direction in u */ 3257117f1b4Smrg du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1)); 3267117f1b4Smrg 3277117f1b4Smrg /* derivative direction in v */ 3287117f1b4Smrg dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0)); 3297117f1b4Smrg 3307117f1b4Smrg /* last bilinear de Casteljau step */ 3317117f1b4Smrg out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) + 3327117f1b4Smrg u * (vs * DCN(1, 0) + v * DCN(1, 1)); 3337117f1b4Smrg } 3347117f1b4Smrg } 3357117f1b4Smrg else if (minorder == uorder) { 3367117f1b4Smrg for (k = 0; k < dim; k++) { 3377117f1b4Smrg /* first bilinear de Casteljau step */ 3387117f1b4Smrg for (i = 0; i < uorder - 1; i++) { 3397117f1b4Smrg DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); 3407117f1b4Smrg for (j = 0; j < vorder - 1; j++) { 3417117f1b4Smrg DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); 3427117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 3437117f1b4Smrg } 3447117f1b4Smrg } 3457117f1b4Smrg 3467117f1b4Smrg /* remaining bilinear de Casteljau steps until the second last step */ 3477117f1b4Smrg for (h = 2; h < minorder - 1; h++) 3487117f1b4Smrg for (i = 0; i < uorder - h; i++) { 3497117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 3507117f1b4Smrg for (j = 0; j < vorder - h; j++) { 3517117f1b4Smrg DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); 3527117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 3537117f1b4Smrg } 3547117f1b4Smrg } 3557117f1b4Smrg 3567117f1b4Smrg /* last bilinear de Casteljau step */ 3577117f1b4Smrg DCN(2, 0) = DCN(1, 0) - DCN(0, 0); 3587117f1b4Smrg DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0); 3597117f1b4Smrg for (j = 0; j < vorder - 1; j++) { 3607117f1b4Smrg /* for the derivative in u */ 3617117f1b4Smrg DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1); 3627117f1b4Smrg DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); 3637117f1b4Smrg 3647117f1b4Smrg /* for the `point' */ 3657117f1b4Smrg DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1); 3667117f1b4Smrg DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); 3677117f1b4Smrg } 3687117f1b4Smrg 3697117f1b4Smrg /* remaining linear de Casteljau steps until the second last step */ 3707117f1b4Smrg for (h = minorder; h < vorder - 1; h++) 3717117f1b4Smrg for (j = 0; j < vorder - h; j++) { 3727117f1b4Smrg /* for the derivative in u */ 3737117f1b4Smrg DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); 3747117f1b4Smrg 3757117f1b4Smrg /* for the `point' */ 3767117f1b4Smrg DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); 3777117f1b4Smrg } 3787117f1b4Smrg 3797117f1b4Smrg /* derivative direction in v */ 3807117f1b4Smrg dv[k] = DCN(0, 1) - DCN(0, 0); 3817117f1b4Smrg 3827117f1b4Smrg /* derivative direction in u */ 3837117f1b4Smrg du[k] = vs * DCN(2, 0) + v * DCN(2, 1); 3847117f1b4Smrg 3857117f1b4Smrg /* last linear de Casteljau step */ 3867117f1b4Smrg out[k] = vs * DCN(0, 0) + v * DCN(0, 1); 3877117f1b4Smrg } 3887117f1b4Smrg } 3897117f1b4Smrg else { /* minorder == vorder */ 3907117f1b4Smrg 3917117f1b4Smrg for (k = 0; k < dim; k++) { 3927117f1b4Smrg /* first bilinear de Casteljau step */ 3937117f1b4Smrg for (i = 0; i < uorder - 1; i++) { 3947117f1b4Smrg DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); 3957117f1b4Smrg for (j = 0; j < vorder - 1; j++) { 3967117f1b4Smrg DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); 3977117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 3987117f1b4Smrg } 3997117f1b4Smrg } 4007117f1b4Smrg 4017117f1b4Smrg /* remaining bilinear de Casteljau steps until the second last step */ 4027117f1b4Smrg for (h = 2; h < minorder - 1; h++) 4037117f1b4Smrg for (i = 0; i < uorder - h; i++) { 4047117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 4057117f1b4Smrg for (j = 0; j < vorder - h; j++) { 4067117f1b4Smrg DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); 4077117f1b4Smrg DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); 4087117f1b4Smrg } 4097117f1b4Smrg } 4107117f1b4Smrg 4117117f1b4Smrg /* last bilinear de Casteljau step */ 4127117f1b4Smrg DCN(0, 2) = DCN(0, 1) - DCN(0, 0); 4137117f1b4Smrg DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1); 4147117f1b4Smrg for (i = 0; i < uorder - 1; i++) { 4157117f1b4Smrg /* for the derivative in v */ 4167117f1b4Smrg DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0); 4177117f1b4Smrg DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); 4187117f1b4Smrg 4197117f1b4Smrg /* for the `point' */ 4207117f1b4Smrg DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1); 4217117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 4227117f1b4Smrg } 4237117f1b4Smrg 4247117f1b4Smrg /* remaining linear de Casteljau steps until the second last step */ 4257117f1b4Smrg for (h = minorder; h < uorder - 1; h++) 4267117f1b4Smrg for (i = 0; i < uorder - h; i++) { 4277117f1b4Smrg /* for the derivative in v */ 4287117f1b4Smrg DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); 4297117f1b4Smrg 4307117f1b4Smrg /* for the `point' */ 4317117f1b4Smrg DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); 4327117f1b4Smrg } 4337117f1b4Smrg 4347117f1b4Smrg /* derivative direction in u */ 4357117f1b4Smrg du[k] = DCN(1, 0) - DCN(0, 0); 4367117f1b4Smrg 4377117f1b4Smrg /* derivative direction in v */ 4387117f1b4Smrg dv[k] = us * DCN(0, 2) + u * DCN(1, 2); 4397117f1b4Smrg 4407117f1b4Smrg /* last linear de Casteljau step */ 4417117f1b4Smrg out[k] = us * DCN(0, 0) + u * DCN(1, 0); 4427117f1b4Smrg } 4437117f1b4Smrg } 4447117f1b4Smrg#undef DCN 4457117f1b4Smrg#undef CN 4467117f1b4Smrg} 4477117f1b4Smrg 4487117f1b4Smrg 4497117f1b4Smrg/* 4507117f1b4Smrg * Do one-time initialization for evaluators. 4517117f1b4Smrg */ 4527117f1b4Smrgvoid 4537117f1b4Smrg_math_init_eval(void) 4547117f1b4Smrg{ 4557117f1b4Smrg GLuint i; 4567117f1b4Smrg 4577117f1b4Smrg /* KW: precompute 1/x for useful x. 4587117f1b4Smrg */ 4597117f1b4Smrg for (i = 1; i < MAX_EVAL_ORDER; i++) 4607117f1b4Smrg inv_tab[i] = 1.0F / i; 4617117f1b4Smrg} 462