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