home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / interp.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  11KB  |  377 lines

  1. /* interp.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: interp.c,v 1.17 1996/02/14 15:40:50 brianp Exp $
  26.  
  27. $Log: interp.c,v $
  28.  * Revision 1.17  1996/02/14  15:40:50  brianp
  29.  * replaced ABS with ABSF, added F suffix to floating point literals
  30.  *
  31.  * Revision 1.16  1996/02/12  19:07:53  brianp
  32.  * applied Bill's Feb 8 patches: change eye Z's to clip W's
  33.  *
  34.  * Revision 1.15  1996/02/01  00:57:45  brianp
  35.  * replaced dummy macro argument 0; with {}
  36.  *
  37.  * Revision 1.14  1996/01/30  19:43:05  brianp
  38.  * added a dummy parameter to two instances of INTERP_TEXCOORD_LOOPS
  39.  * to prevent cpp warnings
  40.  *
  41.  * Revision 1.13  1996/01/24  14:57:59  brianp
  42.  * applied gl_interp_texcoords() patch from Bill Triggs
  43.  *
  44.  * Revision 1.12  1996/01/22  15:38:50  brianp
  45.  * removed gl_interpolate_ub, gl_interpolate_4ub, gl_interpolate_4fixed
  46.  * applied a patch to gl_interp_texcoords(), per Bill Triggs
  47.  *
  48.  * Revision 1.11  1995/12/30  17:16:52  brianp
  49.  * new gl_interp_texcoords function per Bill Triggs
  50.  *
  51.  * Revision 1.10  1995/12/30  00:52:50  brianp
  52.  * added gl_interpolate_4fixed function
  53.  * removed dead code
  54.  *
  55.  * Revision 1.9  1995/12/18  17:29:35  brianp
  56.  * use new GLdepth datatype
  57.  *
  58.  * Revision 1.8  1995/12/12  21:44:59  brianp
  59.  * added gl_interpolate_z() function
  60.  *
  61.  * Revision 1.7  1995/10/23  21:27:54  brianp
  62.  * new GLubyte interpolation using fixed point arithmetic
  63.  *
  64.  * Revision 1.6  1995/06/12  15:43:57  brianp
  65.  * separate GLint and GLubyte interpolation functions
  66.  *
  67.  * Revision 1.5  1995/06/02  13:58:36  brianp
  68.  * faster gl_interpolate(), tried gl_interpolate_rgba()
  69.  *
  70.  * Revision 1.4  1995/05/22  21:02:41  brianp
  71.  * Release 1.2
  72.  *
  73.  * Revision 1.3  1995/03/17  19:15:21  brianp
  74.  * tried to improve gl_interp_texcoords, not much luck
  75.  *
  76.  * Revision 1.2  1995/03/04  19:29:44  brianp
  77.  * 1.1 beta revision
  78.  *
  79.  * Revision 1.1  1995/02/27  22:20:13  brianp
  80.  * Initial revision
  81.  *
  82.  */
  83.  
  84.  
  85. #include "context.h"
  86. #include "macros.h"
  87.  
  88.  
  89.  
  90.  
  91. /*
  92.  * Linear integer interpolation of Z (depth) values:
  93.  * Iterpolate n integer values between z0 and z1 and put into zspan.
  94.  * When finished, zspan[0] = z0, zspan[n-1] = z1, and the rest of
  95.  * zspan[] is filled with interpolated values.
  96.  * We have to be careful to avoid integer overflow!
  97.  */
  98. void gl_interpolate_z( GLint n, GLint z0, GLint z1, GLdepth zspan[] )
  99. {
  100.    GLint i, dz;
  101.  
  102.    switch (n) {
  103.       case 1:
  104.          zspan[0] = z0;
  105.          return;
  106.       case 2:
  107.          zspan[0] = z0;
  108.          zspan[1] = z1;
  109.          return;
  110.       case 3:
  111.          zspan[0] = z0;
  112.          zspan[1] = (z0 + z1) >> 1;
  113.          zspan[2] = z1;
  114.          return;
  115.       default:
  116.          z0 = z0 << 7;
  117.          z1 = z1 << 7;
  118.          dz = (z1-z0) / (n-1);
  119.          for (i=0;i<n;i++) {
  120.             zspan[i] = z0 >> 7;
  121.             z0 += dz;
  122.          }
  123.          return;
  124.    }
  125. }
  126.  
  127.  
  128.  
  129. /*
  130.  * Linear integer interpolation:
  131.  * Iterpolate n integer values between y0 and y1 and put into yspan.
  132.  * When finished, yspan[0] = y0, yspan[n-1] = y1, and the rest of
  133.  * yspan[] is filled with interpolated values.
  134.  */
  135. void gl_interpolate_i( GLint n, GLint y0, GLint y1, GLint yspan[] )
  136. {
  137.    switch (n) {
  138.       case 1:
  139.          yspan[0] = y0;
  140.      return;
  141.       case 2:
  142.          yspan[0] = y0;
  143.          yspan[1] = y1;
  144.      return;
  145.       case 3:
  146.          yspan[0] = y0;
  147.      yspan[1] = (y0+y1) >> 1;
  148.          yspan[2] = y1;
  149.      return;
  150.       default:
  151.      if (y0==y1) {
  152.         register GLint i;
  153.         for (i=0;i<n;i++) {
  154.            yspan[i] = y0;
  155.         }
  156.      }
  157.      else {
  158.         register GLint i;
  159.         register GLint dx, dy;
  160.         register GLint a, b, d;
  161.         register GLint y;
  162.         register GLint qa, qb;
  163.            dx = n-1;
  164.         dy = y1 - y0;
  165.         qa = dy / dx;
  166.         dy = dy % dx;
  167.         if (dy<0) {
  168.            dy = -dy;
  169.            qb = qa - 1;
  170.         }
  171.         else {
  172.            qb = qa + 1;
  173.         }
  174.         a = dy+dy;   d = a-dx;   b = d-dx;
  175.         y = y0;
  176.         for (i=0;i<n;i++) {
  177.            yspan[i] = y;
  178.            if (d<0) {
  179.           d += a;
  180.           y += qa;
  181.            }
  182.            else {
  183.           d += b;
  184.           y += qb;
  185.            }
  186.         }
  187.      }
  188.    }
  189. }
  190.  
  191.  
  192.  
  193. /*
  194.  * Interpolate RGBA values.
  195.  * Input:  n - number of values to generate
  196.  *         r0, r1 - first and last alpha values
  197.  *         g0, g1 - first and last alpha values
  198.  *         b0, b1 - first and last alpha values
  199.  *         a0, a1 - first and last alpha values
  200.  * Output:  rspan, gspan, bspan, aspan - interpolated color values in
  201.  *          the range [0,CC.RedScale], [0,CC.GreenScale], [0,CC.BlueScale],
  202.  *          and [0,CC.AlphaScale].
  203.  */
  204. void gl_interpolate_rgba( GLint n,
  205.                           GLfixed r0, GLfixed r1, GLubyte rspan[],
  206.                           GLfixed g0, GLfixed g1, GLubyte gspan[],
  207.                           GLfixed b0, GLfixed b1, GLubyte bspan[],
  208.                           GLfixed a0, GLfixed a1, GLubyte aspan[] )
  209. {
  210.    GLint i, m;
  211.    GLfixed dr, dg, db, da;
  212.  
  213.    switch (n) {
  214.       case 1:
  215.          rspan[0] = FixedToInt(r0);
  216.          gspan[0] = FixedToInt(g0);
  217.          bspan[0] = FixedToInt(b0);
  218.          aspan[0] = FixedToInt(a0);
  219.      return;
  220.       case 2:
  221.          rspan[0] = FixedToInt(r0);   rspan[1] = FixedToInt(r1);
  222.          gspan[0] = FixedToInt(g0);   gspan[1] = FixedToInt(g1);
  223.          bspan[0] = FixedToInt(b0);   bspan[1] = FixedToInt(b1);
  224.          aspan[0] = FixedToInt(a0);   aspan[1] = FixedToInt(a1);
  225.      return;
  226.       default:
  227.          m = n-1;
  228.          dr = (r1-r0) / m;
  229.          dg = (g1-g0) / m;
  230.          db = (b1-b0) / m;
  231.          da = (a1-a0) / m;
  232.          for (i=0;i<n;i++) {
  233.             rspan[i] = FixedToInt(r0);    r0 += dr;
  234.             gspan[i] = FixedToInt(g0);    g0 += dg;
  235.             bspan[i] = FixedToInt(b0);    b0 += db;
  236.             aspan[i] = FixedToInt(a0);    a0 += da;
  237.          }
  238.          return;
  239.    }
  240. }
  241.  
  242.  
  243.  
  244.  
  245. /* Interpolate texture coordinates. There are several cases so we define
  246.  * a macro for convenience. Depth w can be interpolated affinely or
  247.  * perspectively, with or without the explicit depth values being
  248.  * stored, and for each case there is affine, homogeneous perspective,
  249.  * or inhomogeneous perspective interpolation of 2D (and eventually 3D)
  250.  * texture. Eg, one can have an orthographic (in depth) projection of a
  251.  * projective (in texcoords) texture, etc. The below macro handles the
  252.  * current texture interpolation cases.
  253.  */
  254. #define INTERP_TEXCOORD_LOOPS(DEFINE_MU,EVAL_W)                \
  255. {                                    \
  256.   if (!v) {                                \
  257.     /* Simple affine 2D texture */                    \
  258.     for (i=0;i<n;i++) {                            \
  259.       DEFINE_MU;                            \
  260.       s[i] = s0 + mu * delta_s;                        \
  261.       t[i] = t0 + mu * delta_t;                        \
  262.       EVAL_W                                \
  263.     }                                    \
  264.   } else if (homogeneous) {                        \
  265.     /* Homogeneous interpolation of 2D projective texture        \
  266.      * (down polygon edges) */                        \
  267.     for (i=0;i<n;i++) {                            \
  268.       DEFINE_MU;                            \
  269.       s[i] = s0 + mu * delta_s;                        \
  270.       t[i] = t0 + mu * delta_t;                        \
  271.       v[i] = v0 + mu * delta_v;                        \
  272.       EVAL_W                                \
  273.     }                                    \
  274.   } else {                                \
  275.     /* Inhomogeneous interpolation of 2D projective texture        \
  276.      * (along lines or polygon spans) */                \
  277.     for (i=0;i<n;i++) {                            \
  278.       GLfloat vi;                            \
  279.       DEFINE_MU;                            \
  280.       vi = v0 + mu * delta_v;                        \
  281.       s[i] = (s0 + mu * delta_s)/vi;                    \
  282.       t[i] = (t0 + mu * delta_t)/vi;                    \
  283.       EVAL_W                                \
  284.     }                                    \
  285.   }                                    \
  286. }
  287.  
  288. /*
  289.  * Perform texture coordinate interpolation along a line in window coord-
  290.  * inate space.  Depending on the perspective correction hint we'll either
  291.  * just do simple linear interpolation or interpolation with perspective
  292.  * correction.
  293.  * Input:  n - number of texture coords to produce
  294.  *       homogeneous  - interpolate linearly in homogeneous texture 
  295.  *              coordinates (i.e. do not divide s,t,u by v to get
  296.  *              affine texture space indices).
  297.  *         clipw0, clipw1 - w coordinate of end points in clip coords
  298.  *         s0, s1 - S-component of texture coords at end points
  299.  *         t0, t1 - T-component of texture coords at end points
  300.  *         u0, u1 - U-component of texture coords at end points
  301.  *         v0, v1 - V-component of texture coords at end points
  302.  * Output:  s, t, u, v - resulting arrays of S, T, U, V texture coordinates
  303.  *          w - interpolated W-component of clip coordinates along the line
  304.  *              (note that w can be a NULL pointer if w isn't needed)
  305.  */
  306. void gl_interp_texcoords( GLuint n, GLboolean homogeneous,
  307.               GLfloat clipw0, GLfloat clipw1,
  308.               GLfloat s0, GLfloat s1,
  309.               GLfloat t0, GLfloat t1,
  310.               GLfloat u0, GLfloat u1,
  311.               GLfloat v0, GLfloat v1,
  312.               GLfloat s[], GLfloat t[], GLfloat u[], GLfloat v[],
  313.               GLfloat w[])
  314. {
  315.    /*
  316.     * This implementation of this function contributed by
  317.     * Bill Triggs  <Bill.Triggs@imag.fr>.  Thanks Bill!
  318.     */
  319.  
  320.    if (n==1) {
  321.       if (homogeneous) {
  322.          s[0] = s0;
  323.          t[0] = t0;
  324.          v[0] = v0;
  325.       }
  326.       else {
  327.          s[0] = s0/v0;
  328.          t[0] = t0/v0;
  329.       }
  330.       if (w)  w[0] = clipw0;
  331.    }
  332.    else {
  333.       GLfloat delta_clipw = clipw1 - clipw0;
  334.       GLfloat delta_s = s1 - s0;
  335.       GLfloat delta_t = t1 - t0;
  336.       GLfloat delta_v = v1 - v0;
  337.       GLuint i;
  338.  
  339.       if (!homogeneous && v0==1.0F && v1==1.0F) {
  340.     /* avoid trivial v scalings */
  341.     v = 0;
  342.       }
  343.       if (CC.ProjectionMatrix[14]==0.0F
  344.           || CC.Hint.PerspectiveCorrection==GL_FASTEST
  345.       || ABSF(delta_clipw)<0.001F*ABSF(clipw0+clipw1)) {
  346.          /* Affine interpolation in depth -- orthographic or 
  347.         almost frontal perspective projection. */
  348.     if (w) {
  349.       INTERP_TEXCOORD_LOOPS(GLfloat mu = (GLfloat) i / (n-1),
  350.                 w[i] = clipw0 + mu * delta_clipw;);
  351.     }
  352.     else {
  353.       INTERP_TEXCOORD_LOOPS(GLfloat mu = (GLfloat) i / (n-1), {} );
  354.     }
  355.       }
  356.       else {
  357.     /* Full perspective interpolation in depth (w<=0) */
  358.  
  359.      if (clipw0<1e-20) clipw0=1e-20;
  360.      if (clipw1<1e-20) clipw1=1e-20;
  361.  
  362.      if (w) {
  363.        INTERP_TEXCOORD_LOOPS
  364.          (GLfloat w0i = clipw0 * i; 
  365.           GLfloat mu = w0i / (clipw1 * (n-1-i) + w0i),
  366.           w[i] = clipw0 + mu * delta_clipw;);
  367.      }
  368.      else {
  369.        INTERP_TEXCOORD_LOOPS
  370.          (GLfloat w0i = clipw0 * i; 
  371.           GLfloat mu = w0i / (clipw1 * (n-1-i) + w0i), {} );
  372.      }
  373.        }
  374.     }
  375. }
  376.  
  377.