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