ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

m_eval.c
Go to the documentation of this file.
00001 
00002 /*
00003  * Mesa 3-D graphics library
00004  * Version:  3.5
00005  *
00006  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this software and associated documentation files (the "Software"),
00010  * to deal in the Software without restriction, including without limitation
00011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00012  * and/or sell copies of the Software, and to permit persons to whom the
00013  * Software is furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included
00016  * in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00021  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00022  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00023  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00024  */
00025 
00026 
00027 /*
00028  * eval.c was written by
00029  * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
00030  * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
00031  *
00032  * My original implementation of evaluators was simplistic and didn't
00033  * compute surface normal vectors properly.  Bernd and Volker applied
00034  * used more sophisticated methods to get better results.
00035  *
00036  * Thanks guys!
00037  */
00038 
00039 
00040 #include "main/glheader.h"
00041 #include "main/config.h"
00042 #include "m_eval.h"
00043 
00044 static GLfloat inv_tab[MAX_EVAL_ORDER];
00045 
00046 
00047 
00048 /*
00049  * Horner scheme for Bezier curves
00050  *
00051  * Bezier curves can be computed via a Horner scheme.
00052  * Horner is numerically less stable than the de Casteljau
00053  * algorithm, but it is faster. For curves of degree n
00054  * the complexity of Horner is O(n) and de Casteljau is O(n^2).
00055  * Since stability is not important for displaying curve
00056  * points I decided to use the Horner scheme.
00057  *
00058  * A cubic Bezier curve with control points b0, b1, b2, b3 can be
00059  * written as
00060  *
00061  *        (([3]        [3]     )     [3]       )     [3]
00062  * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
00063  *
00064  *                                           [n]
00065  * where s=1-t and the binomial coefficients [i]. These can
00066  * be computed iteratively using the identity:
00067  *
00068  * [n]               [n  ]             [n]
00069  * [i] = (n-i+1)/i * [i-1]     and     [0] = 1
00070  */
00071 
00072 
00073 void
00074 _math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t,
00075               GLuint dim, GLuint order)
00076 {
00077    GLfloat s, powert, bincoeff;
00078    GLuint i, k;
00079 
00080    if (order >= 2) {
00081       bincoeff = (GLfloat) (order - 1);
00082       s = 1.0F - t;
00083 
00084       for (k = 0; k < dim; k++)
00085      out[k] = s * cp[k] + bincoeff * t * cp[dim + k];
00086 
00087       for (i = 2, cp += 2 * dim, powert = t * t; i < order;
00088        i++, powert *= t, cp += dim) {
00089      bincoeff *= (GLfloat) (order - i);
00090      bincoeff *= inv_tab[i];
00091 
00092      for (k = 0; k < dim; k++)
00093         out[k] = s * out[k] + bincoeff * powert * cp[k];
00094       }
00095    }
00096    else {           /* order=1 -> constant curve */
00097 
00098       for (k = 0; k < dim; k++)
00099      out[k] = cp[k];
00100    }
00101 }
00102 
00103 /*
00104  * Tensor product Bezier surfaces
00105  *
00106  * Again the Horner scheme is used to compute a point on a
00107  * TP Bezier surface. First a control polygon for a curve
00108  * on the surface in one parameter direction is computed,
00109  * then the point on the curve for the other parameter
00110  * direction is evaluated.
00111  *
00112  * To store the curve control polygon additional storage
00113  * for max(uorder,vorder) points is needed in the
00114  * control net cn.
00115  */
00116 
00117 void
00118 _math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v,
00119              GLuint dim, GLuint uorder, GLuint vorder)
00120 {
00121    GLfloat *cp = cn + uorder * vorder * dim;
00122    GLuint i, uinc = vorder * dim;
00123 
00124    if (vorder > uorder) {
00125       if (uorder >= 2) {
00126      GLfloat s, poweru, bincoeff;
00127      GLuint j, k;
00128 
00129      /* Compute the control polygon for the surface-curve in u-direction */
00130      for (j = 0; j < vorder; j++) {
00131         GLfloat *ucp = &cn[j * dim];
00132 
00133         /* Each control point is the point for parameter u on a */
00134         /* curve defined by the control polygons in u-direction */
00135         bincoeff = (GLfloat) (uorder - 1);
00136         s = 1.0F - u;
00137 
00138         for (k = 0; k < dim; k++)
00139            cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k];
00140 
00141         for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder;
00142          i++, poweru *= u, ucp += uinc) {
00143            bincoeff *= (GLfloat) (uorder - i);
00144            bincoeff *= inv_tab[i];
00145 
00146            for (k = 0; k < dim; k++)
00147           cp[j * dim + k] =
00148              s * cp[j * dim + k] + bincoeff * poweru * ucp[k];
00149         }
00150      }
00151 
00152      /* Evaluate curve point in v */
00153      _math_horner_bezier_curve(cp, out, v, dim, vorder);
00154       }
00155       else          /* uorder=1 -> cn defines a curve in v */
00156      _math_horner_bezier_curve(cn, out, v, dim, vorder);
00157    }
00158    else {           /* vorder <= uorder */
00159 
00160       if (vorder > 1) {
00161      GLuint i;
00162 
00163      /* Compute the control polygon for the surface-curve in u-direction */
00164      for (i = 0; i < uorder; i++, cn += uinc) {
00165         /* For constant i all cn[i][j] (j=0..vorder) are located */
00166         /* on consecutive memory locations, so we can use        */
00167         /* horner_bezier_curve to compute the control points     */
00168 
00169         _math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder);
00170      }
00171 
00172      /* Evaluate curve point in u */
00173      _math_horner_bezier_curve(cp, out, u, dim, uorder);
00174       }
00175       else          /* vorder=1 -> cn defines a curve in u */
00176      _math_horner_bezier_curve(cn, out, u, dim, uorder);
00177    }
00178 }
00179 
00180 /*
00181  * The direct de Casteljau algorithm is used when a point on the
00182  * surface and the tangent directions spanning the tangent plane
00183  * should be computed (this is needed to compute normals to the
00184  * surface). In this case the de Casteljau algorithm approach is
00185  * nicer because a point and the partial derivatives can be computed
00186  * at the same time. To get the correct tangent length du and dv
00187  * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
00188  * Since only the directions are needed, this scaling step is omitted.
00189  *
00190  * De Casteljau needs additional storage for uorder*vorder
00191  * values in the control net cn.
00192  */
00193 
00194 void
00195 _math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du,
00196             GLfloat * dv, GLfloat u, GLfloat v, GLuint dim,
00197             GLuint uorder, GLuint vorder)
00198 {
00199    GLfloat *dcn = cn + uorder * vorder * dim;
00200    GLfloat us = 1.0F - u, vs = 1.0F - v;
00201    GLuint h, i, j, k;
00202    GLuint minorder = uorder < vorder ? uorder : vorder;
00203    GLuint uinc = vorder * dim;
00204    GLuint dcuinc = vorder;
00205 
00206    /* Each component is evaluated separately to save buffer space  */
00207    /* This does not drasticaly decrease the performance of the     */
00208    /* algorithm. If additional storage for (uorder-1)*(vorder-1)   */
00209    /* points would be available, the components could be accessed  */
00210    /* in the innermost loop which could lead to less cache misses. */
00211 
00212 #define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
00213 #define DCN(I, J) dcn[(I)*dcuinc+(J)]
00214    if (minorder < 3) {
00215       if (uorder == vorder) {
00216      for (k = 0; k < dim; k++) {
00217         /* Derivative direction in u */
00218         du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) +
00219            v * (CN(1, 1, k) - CN(0, 1, k));
00220 
00221         /* Derivative direction in v */
00222         dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) +
00223            u * (CN(1, 1, k) - CN(1, 0, k));
00224 
00225         /* bilinear de Casteljau step */
00226         out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) +
00227            u * (vs * CN(1, 0, k) + v * CN(1, 1, k));
00228      }
00229       }
00230       else if (minorder == uorder) {
00231      for (k = 0; k < dim; k++) {
00232         /* bilinear de Casteljau step */
00233         DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k);
00234         DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k);
00235 
00236         for (j = 0; j < vorder - 1; j++) {
00237            /* for the derivative in u */
00238            DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k);
00239            DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
00240 
00241            /* for the `point' */
00242            DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k);
00243            DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
00244         }
00245 
00246         /* remaining linear de Casteljau steps until the second last step */
00247         for (h = minorder; h < vorder - 1; h++)
00248            for (j = 0; j < vorder - h; j++) {
00249           /* for the derivative in u */
00250           DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
00251 
00252           /* for the `point' */
00253           DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
00254            }
00255 
00256         /* derivative direction in v */
00257         dv[k] = DCN(0, 1) - DCN(0, 0);
00258 
00259         /* derivative direction in u */
00260         du[k] = vs * DCN(1, 0) + v * DCN(1, 1);
00261 
00262         /* last linear de Casteljau step */
00263         out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
00264      }
00265       }
00266       else {            /* minorder == vorder */
00267 
00268      for (k = 0; k < dim; k++) {
00269         /* bilinear de Casteljau step */
00270         DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k);
00271         DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k);
00272         for (i = 0; i < uorder - 1; i++) {
00273            /* for the derivative in v */
00274            DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k);
00275            DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
00276 
00277            /* for the `point' */
00278            DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k);
00279            DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00280         }
00281 
00282         /* remaining linear de Casteljau steps until the second last step */
00283         for (h = minorder; h < uorder - 1; h++)
00284            for (i = 0; i < uorder - h; i++) {
00285           /* for the derivative in v */
00286           DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
00287 
00288           /* for the `point' */
00289           DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00290            }
00291 
00292         /* derivative direction in u */
00293         du[k] = DCN(1, 0) - DCN(0, 0);
00294 
00295         /* derivative direction in v */
00296         dv[k] = us * DCN(0, 1) + u * DCN(1, 1);
00297 
00298         /* last linear de Casteljau step */
00299         out[k] = us * DCN(0, 0) + u * DCN(1, 0);
00300      }
00301       }
00302    }
00303    else if (uorder == vorder) {
00304       for (k = 0; k < dim; k++) {
00305      /* first bilinear de Casteljau step */
00306      for (i = 0; i < uorder - 1; i++) {
00307         DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
00308         for (j = 0; j < vorder - 1; j++) {
00309            DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
00310            DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00311         }
00312      }
00313 
00314      /* remaining bilinear de Casteljau steps until the second last step */
00315      for (h = 2; h < minorder - 1; h++)
00316         for (i = 0; i < uorder - h; i++) {
00317            DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00318            for (j = 0; j < vorder - h; j++) {
00319           DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
00320           DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00321            }
00322         }
00323 
00324      /* derivative direction in u */
00325      du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1));
00326 
00327      /* derivative direction in v */
00328      dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0));
00329 
00330      /* last bilinear de Casteljau step */
00331      out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) +
00332         u * (vs * DCN(1, 0) + v * DCN(1, 1));
00333       }
00334    }
00335    else if (minorder == uorder) {
00336       for (k = 0; k < dim; k++) {
00337      /* first bilinear de Casteljau step */
00338      for (i = 0; i < uorder - 1; i++) {
00339         DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
00340         for (j = 0; j < vorder - 1; j++) {
00341            DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
00342            DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00343         }
00344      }
00345 
00346      /* remaining bilinear de Casteljau steps until the second last step */
00347      for (h = 2; h < minorder - 1; h++)
00348         for (i = 0; i < uorder - h; i++) {
00349            DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00350            for (j = 0; j < vorder - h; j++) {
00351           DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
00352           DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00353            }
00354         }
00355 
00356      /* last bilinear de Casteljau step */
00357      DCN(2, 0) = DCN(1, 0) - DCN(0, 0);
00358      DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0);
00359      for (j = 0; j < vorder - 1; j++) {
00360         /* for the derivative in u */
00361         DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1);
00362         DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
00363 
00364         /* for the `point' */
00365         DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1);
00366         DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
00367      }
00368 
00369      /* remaining linear de Casteljau steps until the second last step */
00370      for (h = minorder; h < vorder - 1; h++)
00371         for (j = 0; j < vorder - h; j++) {
00372            /* for the derivative in u */
00373            DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
00374 
00375            /* for the `point' */
00376            DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
00377         }
00378 
00379      /* derivative direction in v */
00380      dv[k] = DCN(0, 1) - DCN(0, 0);
00381 
00382      /* derivative direction in u */
00383      du[k] = vs * DCN(2, 0) + v * DCN(2, 1);
00384 
00385      /* last linear de Casteljau step */
00386      out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
00387       }
00388    }
00389    else {           /* minorder == vorder */
00390 
00391       for (k = 0; k < dim; k++) {
00392      /* first bilinear de Casteljau step */
00393      for (i = 0; i < uorder - 1; i++) {
00394         DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
00395         for (j = 0; j < vorder - 1; j++) {
00396            DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
00397            DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00398         }
00399      }
00400 
00401      /* remaining bilinear de Casteljau steps until the second last step */
00402      for (h = 2; h < minorder - 1; h++)
00403         for (i = 0; i < uorder - h; i++) {
00404            DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00405            for (j = 0; j < vorder - h; j++) {
00406           DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
00407           DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
00408            }
00409         }
00410 
00411      /* last bilinear de Casteljau step */
00412      DCN(0, 2) = DCN(0, 1) - DCN(0, 0);
00413      DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1);
00414      for (i = 0; i < uorder - 1; i++) {
00415         /* for the derivative in v */
00416         DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0);
00417         DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
00418 
00419         /* for the `point' */
00420         DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1);
00421         DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00422      }
00423 
00424      /* remaining linear de Casteljau steps until the second last step */
00425      for (h = minorder; h < uorder - 1; h++)
00426         for (i = 0; i < uorder - h; i++) {
00427            /* for the derivative in v */
00428            DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
00429 
00430            /* for the `point' */
00431            DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
00432         }
00433 
00434      /* derivative direction in u */
00435      du[k] = DCN(1, 0) - DCN(0, 0);
00436 
00437      /* derivative direction in v */
00438      dv[k] = us * DCN(0, 2) + u * DCN(1, 2);
00439 
00440      /* last linear de Casteljau step */
00441      out[k] = us * DCN(0, 0) + u * DCN(1, 0);
00442       }
00443    }
00444 #undef DCN
00445 #undef CN
00446 }
00447 
00448 
00449 /*
00450  * Do one-time initialization for evaluators.
00451  */
00452 void
00453 _math_init_eval(void)
00454 {
00455    GLuint i;
00456 
00457    /* KW: precompute 1/x for useful x.
00458     */
00459    for (i = 1; i < MAX_EVAL_ORDER; i++)
00460       inv_tab[i] = 1.0F / i;
00461 }

Generated on Sun May 27 2012 04:20:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.