Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

Triangle.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  Triangle.c                                                                          */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description:  Edge and Gradient calculations for triangle rasterizater              */
00006 /*                                                                                      */
00007 /*  Code fragments from Chris Hecker's texture mapping articles used with               */
00008 /*  permission.  http://www.d6.com/users/checker                                        */
00009 /*                                                                                      */
00010 /*  The contents of this file are subject to the Genesis3D Public License               */
00011 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00012 /*  compliance with the License. You may obtain a copy of the License at                */
00013 /*  http://www.genesis3d.com                                                            */
00014 /*                                                                                      */
00015 /*  Software distributed under the License is distributed on an "AS IS"                 */
00016 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00017 /*  the License for the specific language governing rights and limitations              */
00018 /*  under the License.                                                                  */
00019 /*                                                                                      */
00020 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00021 /*Genesis3D Version 1.1 released November 15, 1999                            */
00022 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00023 /*                                                                                      */
00024 /****************************************************************************************/
00025 #if 0
00026 // for debugging
00027 #include <stdio.h>              //sprintf
00028 #include <windows.h>    //OutputDebugString()
00029 #endif
00030 
00031 #include <assert.h>
00032 #include <math.h>               // fabs
00033 #include <string.h>             // memcpy
00034 #include "swthandle.h"
00035 #include "basetype.h"
00036 #include "triangle.h"
00037 
00038 
00039 
00040 #ifndef USE_DIBS
00041 #define DEST565 
00042 #endif
00043 
00044 
00045 
00046 
00047 
00048 #define MAX(AA,BB)  ((AA)>(BB)?(AA):(BB))
00049 #define MIN(AA,BB)  ((AA)<(BB)?(AA):(BB))
00050 
00051 
00052 geBoolean GENESISCC Triangle_GradientsCompute( 
00053                                         Triangle_Gradients *G, 
00054                                         const DRV_TLVertex *pVertices, 
00055                                         geFloat TextureWidth, 
00056                                         geFloat TextureHeight)
00057 {
00058         geFloat OneOverdX;
00059         geFloat OneOverdY;
00060         geFloat Denominator;
00061         geFloat Width02  = pVertices[0].x-pVertices[2].x;
00062         geFloat Height02 = pVertices[0].y-pVertices[2].y;
00063         geFloat Width12  = pVertices[1].x-pVertices[2].x;
00064         geFloat Height12 = pVertices[1].y-pVertices[2].y;
00065         geFloat d02,d12;
00066         geFloat Size;
00067         assert( pVertices[0].z != 0.0f );
00068         assert( pVertices[1].z != 0.0f );
00069         assert( pVertices[2].z != 0.0f );
00070         
00071         Denominator = ( (Width12 * Height02) - (Width02 * Height12));
00072 
00073 
00074         if (Denominator == 0.0f)
00075                 return GE_FALSE;
00076 
00077         OneOverdX = 1.0f / Denominator;
00078 
00079         OneOverdY = -OneOverdX;
00080 
00081         {
00082                 geFloat Right   = MAX(pVertices[0].x,MAX(pVertices[1].x,pVertices[2].x));
00083                 geFloat Left    = MIN(pVertices[0].x,MIN(pVertices[1].x,pVertices[2].x));
00084                 geFloat Top     = MIN(pVertices[0].y,MIN(pVertices[1].y,pVertices[2].y));
00085                 geFloat Bottom  = MAX(pVertices[0].y,MAX(pVertices[1].y,pVertices[2].y));
00086                 Size = MAX(Right-Left,Bottom-Top);
00087         }
00088 
00089         if (Size < Triangle.MaxAffineSize)
00090                 G->Affine = 1;
00091         else
00092                 G->Affine = 0;
00093 
00094 
00095         if (Triangle.ROPFlags & (TMAP | ZBUF))
00096                 {
00097                         geFloat zmax = MAX(pVertices[0].z,MAX(pVertices[1].z,pVertices[2].z));
00098                         geFloat zmin = MIN(pVertices[0].z,MIN(pVertices[1].z,pVertices[2].z));
00099                         // G->FZScale is used to scale the range of all the interpolators to fit nicely 
00100                         // in the predeterminted fixed point ranges.  These fixed point ranges are setup
00101                         // to minimize visible errors.
00102                         // The following code is unfortunate.  Due to the limited range of the fixed 
00103                         // point math, the FZScale has a limited ability to scale everything else.
00104                         // the following ranges are uesd to keep FZScale within known good boundries. 
00105                         //   It's still possible to break the rasterizer by using Z values that are too 
00106                         //   large or too small.
00107                         if (zmax-zmin > 255.0f ) 
00108                                 {
00109                                         G->FZScale = zmin;
00110                                 }
00111                         else
00112                                 {
00113                                         if (zmin<80.0f) 
00114                                                 G->FZScale = zmin;
00115                                         else
00116                                                 {
00117                                                         if (zmax>500.0f) zmax=500.0f;
00118                                                         G->FZScale = zmax;
00119                                                 }
00120                                 }
00121                         #if 0
00122                                 {// debugging code:
00123                                         char s[1000];
00124                                         sprintf(s,"z[0]=%f\t\tz[1]=%f\t\tz[2]=%f\t\tScale=%f\n",
00125                                                 pVertices[0].z,pVertices[1].z,pVertices[2].z,G->FZScale);
00126                                         OutputDebugString(s);
00127                                 }
00128                         #endif
00129                         if (!G->Affine)
00130                                 {               
00131                                         G->OneOverZ[0] = G->FZScale/pVertices[0].z;
00132                                         G->OneOverZ[1] = G->FZScale/pVertices[1].z;
00133                                         G->OneOverZ[2] = G->FZScale/pVertices[2].z;
00134                                 }
00135                         else
00136                                 {
00137                                         geFloat OneOverZScale = 1.0f / G->FZScale;
00138                                         G->OneOverZ[0] = pVertices[0].z  * OneOverZScale;
00139                                         G->OneOverZ[1] = pVertices[1].z  * OneOverZScale;
00140                                         G->OneOverZ[2] = pVertices[2].z  * OneOverZScale;
00141                                 }
00142 
00143                         d02 = G->OneOverZ[0] - G->OneOverZ[2];
00144                         d12 = G->OneOverZ[1] - G->OneOverZ[2];
00145                         G->FdOneOverZdX = OneOverdX *  ((d12 * Height02) - (d02 * Height12));
00146                         G->dOneOverZdY = OneOverdY *  ((d12 * Width02 ) - (d02 * Width12 ));
00147                 
00148                         G->dOneOverZdX = FXFL_OOZ(G->FdOneOverZdX);
00149                         G->ZScale      =  FXFL_Z(G->FZScale);
00150                 }
00151 
00152         if (Triangle.ROPFlags & TMAP)           
00153                 {
00154                         G->UOverZ[0]   = ((pVertices[0].u * TextureWidth )+ 0.5f);
00155                         G->VOverZ[0]   = ((pVertices[0].v * TextureHeight)+ 0.5f);
00156                         G->UOverZ[1]   = ((pVertices[1].u * TextureWidth )+ 0.5f);
00157                         G->VOverZ[1]   = ((pVertices[1].v * TextureHeight)+ 0.5f);
00158                         G->UOverZ[2]   = ((pVertices[2].u * TextureWidth )+ 0.5f);
00159                         G->VOverZ[2]   = ((pVertices[2].v * TextureHeight) + 0.5f);
00160                         
00161                         if (!G->Affine)
00162                                 {               
00163                                         G->UOverZ[0]   *=  G->OneOverZ[0];
00164                                         G->VOverZ[0]   *=  G->OneOverZ[0];
00165                                         G->UOverZ[1]   *=  G->OneOverZ[1];
00166                                         G->VOverZ[1]   *=  G->OneOverZ[1];
00167                                         G->UOverZ[2]   *=  G->OneOverZ[2];
00168                                         G->VOverZ[2]   *=  G->OneOverZ[2];
00169                                 }
00170                 
00171 
00172                         d02 = G->UOverZ[0] - G->UOverZ[2];
00173                         d12 = G->UOverZ[1] - G->UOverZ[2];
00174                         G->FdUOverZdX   = OneOverdX *  ((d12 * Height02) - (d02 * Height12));
00175                         G->dUOverZdY   = OneOverdY *  ((d12 * Width02 ) - (d02 * Width12 ));
00176 
00177                         d02 = G->VOverZ[0] - G->VOverZ[2];
00178                         d12 = G->VOverZ[1] - G->VOverZ[2];
00179                         G->FdVOverZdX   = OneOverdX *  ((d12 * Height02) - (d02 * Height12));
00180                         G->dVOverZdY   = OneOverdY *  ((d12 * Width02 ) - (d02 * Width12));
00181 
00182                         G->dUOverZdX   =  FXFL_OZ(G->FdUOverZdX);
00183                         G->dVOverZdX   =  FXFL_OZ(G->FdVOverZdX);
00184                 }
00185                                         
00186 
00187         if (Triangle.ROPFlags & LSHADE)
00188                 {
00189                         // can clamp these things higher to remove more small negative overruns.  
00190                         d02 = (pVertices[0].r) - (pVertices[2].r);
00191                         d12 = (pVertices[1].r) - (pVertices[2].r);
00192                         G->FdRdX = OneOverdX * ((d12 * Height02) - (d02 * Height12));
00193                         G->dRdY  = OneOverdY * ((d12 * Width02) - (d02 * Width12));
00194 
00195                         d02 = (pVertices[0].g) - (pVertices[2].g);
00196                         d12 = (pVertices[1].g) - (pVertices[2].g);
00197                         G->FdGdX = OneOverdX * ((d12 * Height02) - (d02 * Height12));
00198                         G->dGdY  = OneOverdY * ((d12 * Width02) - (d02 * Width12));
00199 
00200                         d02 = (pVertices[0].b) - (pVertices[2].b);
00201                         d12 = (pVertices[1].b) - (pVertices[2].b);
00202                         G->FdBdX = OneOverdX * ((d12 * Height02) - (d02 * Height12));
00203                         G->dBdY  = OneOverdY * ((d12 * Width02) - (d02 * Width12));
00204 
00205                         G->dRdX = FXFL_RGB(G->FdRdX);
00206                         G->dGdX = FXFL_RGB(G->FdGdX);
00207                         G->dBdX = FXFL_RGB(G->FdBdX);
00208                 }
00209         
00210         if (!G->Affine)
00211                 {
00212                         geFloat ChangeIndicator = (geFloat)fabs(G->FdOneOverZdX) + (geFloat)fabs(G->dOneOverZdY);
00213 
00214                         if (Triangle.ROPFlags & LMAP) 
00215                                 {
00216                                         // can maybe infer from the lightmap density what's best to do here.
00217                                         G->SubSpanWidth = 16;
00218                                         G->SubSpanShift  = 4;
00219                                 }
00220                         else
00221                                 {
00222                                         if ( ChangeIndicator < 0.0005f) 
00223                                                 {
00224                                                         G->SubSpanWidth = 128;
00225                                                         G->SubSpanShift  = 7;
00226                                                 }
00227                                         else if ( ChangeIndicator < 0.001f) 
00228                                                 {
00229                                                         G->SubSpanWidth = 64;
00230                                                         G->SubSpanShift  = 6;
00231                                                 }
00232                                         else if ( ChangeIndicator < 0.005f)
00233                                                 {
00234                                                         G->SubSpanWidth = 32;
00235                                                         G->SubSpanShift  = 5;
00236                                                 }
00237                                         else
00238                                                 {
00239                                                         G->SubSpanWidth = 16;
00240                                                         G->SubSpanShift  = 4;
00241                                                 }
00242                                 }
00243                 }
00244         else
00245                 {
00246                         G->dOneOverZdX = OOZ_FXP_TO_16_16(G->dOneOverZdX) * Z_FXP_TO_INT(G->ZScale);
00247                         G->dUOverZdX   = OZ_FXP_TO_16_16 (G->dUOverZdX);
00248                         G->dVOverZdX   = OZ_FXP_TO_16_16 (G->dVOverZdX);
00249                 }
00250 
00251         return GE_TRUE;
00252 }
00253 
00254 void GENESISCC FloorDivMod( int32 Numerator, int32 Denominator, int32 *Floor,
00255                                 int32 *Mod )
00256 {
00257         assert(Denominator > 0);                // we assume it's positive
00258         if(Numerator >= 0) 
00259                 {
00260                         // positive case, C is okay
00261                         *Floor = Numerator / Denominator;
00262                         *Mod   = Numerator % Denominator;
00263                 } 
00264         else 
00265                 {
00266                         // Numerator is negative, do the right thing
00267                         *Floor = -((-Numerator) / Denominator);
00268                         *Mod   =   (-Numerator) % Denominator;
00269                         if(*Mod) 
00270                                 {
00271                                         // there is a remainder
00272                                         *Floor = *Floor -1; 
00273                                         *Mod = Denominator - *Mod;
00274                                 }
00275                 }
00276 }
00277 
00278 static int32 GENESISCC Ceil28_4( int32 Value ) 
00279 {
00280         int32 ReturnValue;
00281         int32 Numerator = Value - 1 + 16;
00282         if(Numerator >= 0) 
00283                 {
00284                         ReturnValue = Numerator/16;
00285                 } 
00286         else 
00287                 {
00288                         // deal with negative numerators correctly
00289                         ReturnValue = -((-Numerator)/16);
00290                         ReturnValue -= ((-Numerator) % 16) ? 1 : 0;
00291                 }
00292         return ReturnValue;
00293 }
00294 
00295 void GENESISCC Triangle_EdgeCompute( 
00296                 Triangle_Edge *E, 
00297                 const Triangle_Gradients *Gradients, 
00298                 const DRV_TLVertex *pVertices, 
00299                 int Top, 
00300                 int Bottom,
00301                 int IsLeftEdge)
00302 {
00303         int YEnd;
00304         int TopY,BottomY,TopX=0,BottomX;
00305         TopY    = (int32)(pVertices[Top].y * 16.0f);
00306         BottomY = (int32)(pVertices[Bottom].y * 16.0f); 
00307         E->Y = Ceil28_4( TopY );
00308         YEnd = Ceil28_4( BottomY );
00309         E->Height       = YEnd - E->Y;
00310 
00311         if (!E->Height)
00312                 return;
00313 
00314         {
00315                 int32 dN = BottomY-TopY;
00316                 if (dN > 0)
00317                         {
00318                                 int32 dM,InitialNumerator;
00319                                 //int32 dM   = (int32)(FWidth  * 16.0f);
00320                                 TopX    = (int32)(pVertices[Top].x * 16.0f);
00321                                 BottomX = (int32)(pVertices[Bottom].x * 16.0f);
00322                                 dM = BottomX - TopX;
00323                         
00324                                 InitialNumerator = dM*16*E->Y - dM*TopY +       dN*TopX - 1 + dN*16;
00325                                 FloorDivMod(InitialNumerator,dN*16,&(E->X),&(E->ErrorTerm));
00326                                 FloorDivMod(dM*16,dN*16,&(E->XStep),&(E->Numerator));
00327                                 E->Denominator = dN*16;
00328                         }
00329                 else
00330                         {
00331                                 E->XStep=0;
00332                                 E->X = (int)(pVertices[Top].x);
00333                         }
00334         }
00335 
00336         if (IsLeftEdge)
00337                 {
00338                         geFloat XPrestep                = E->X - (geFloat)TopX * (1.0f/16.0f);
00339                         geFloat YPrestep                = E->Y - (geFloat)TopY * (1.0f/16.0f);
00340                         
00341                         if (Triangle.ROPFlags & (TMAP | ZBUF))
00342                                 {
00343                                         E->OneOverZ             = FXFL_OOZ(Gradients->OneOverZ[Top] + YPrestep * Gradients->dOneOverZdY + XPrestep * Gradients->FdOneOverZdX);
00344                                         E->OneOverZStep = FXFL_OOZ(E->XStep * Gradients->FdOneOverZdX   + Gradients->dOneOverZdY);
00345                                         E->dOneOverZdX  = Gradients->dOneOverZdX;
00346                                 }
00347 
00348                         if (Triangle.ROPFlags & TMAP)
00349                                 {
00350                                         E->UOverZ               = FXFL_OZ(Gradients->UOverZ[Top]        + YPrestep * Gradients->dUOverZdY       + XPrestep * Gradients->FdUOverZdX);
00351                                         E->UOverZStep   = FXFL_OZ(E->XStep * Gradients->FdUOverZdX + Gradients->dUOverZdY);
00352                                         E->dUOverZdX    = Gradients->dUOverZdX;
00353 
00354                                         E->VOverZ               = FXFL_OZ(Gradients->VOverZ[Top]        + YPrestep * Gradients->dVOverZdY       + XPrestep * Gradients->FdVOverZdX);
00355                                         E->VOverZStep   = FXFL_OZ(E->XStep * Gradients->FdVOverZdX + Gradients->dVOverZdY);
00356                                         E->dVOverZdX    = Gradients->dVOverZdX;
00357                                 }
00358 
00359                         if (Triangle.ROPFlags & LSHADE)
00360                                 {
00361                                         E->R                    = FXFL_RGB( (pVertices[Top].r) + 0.5f   + YPrestep * Gradients->dRdY            + XPrestep * Gradients->FdRdX);
00362                                         E->RStep                = FXFL_RGB(E->XStep * Gradients->FdRdX + Gradients->dRdY);
00363                                         E->dRdX                 = Gradients->dRdX;
00364 
00365                                         E->G                    = FXFL_RGB( (pVertices[Top].g) + 0.5f   + YPrestep * Gradients->dGdY            + XPrestep * Gradients->FdGdX);
00366                                         E->GStep                = FXFL_RGB(E->XStep * Gradients->FdGdX + Gradients->dGdY);
00367                                         E->dGdX                 = Gradients->dGdX;
00368 
00369                                         E->B                    = FXFL_RGB( (pVertices[Top].b) + 0.5f   + YPrestep * Gradients->dBdY            + XPrestep * Gradients->FdBdX);
00370                                         E->BStep                = FXFL_RGB(E->XStep * Gradients->FdBdX + Gradients->dBdY);
00371                                         E->dBdX                 = Gradients->dBdX;
00372                                 }
00373 
00374                         if (Gradients->Affine)
00375                                 {
00376                                         if (Triangle.ROPFlags & (TMAP | ZBUF))
00377                                                 {
00378                                                         E->OneOverZ     = OOZ_FXP_TO_16_16(     E->OneOverZ             )  * Z_FXP_TO_INT(Gradients->ZScale);
00379                                                         E->OneOverZStep = OOZ_FXP_TO_16_16(     E->OneOverZStep )  * Z_FXP_TO_INT(Gradients->ZScale);
00380                                                 }
00381                                         if (Triangle.ROPFlags & TMAP)
00382                                                 {
00383                                                         E->UOverZ               = OZ_FXP_TO_16_16 (     E->UOverZ               );
00384                                                         E->UOverZStep   = OZ_FXP_TO_16_16 (     E->UOverZStep   );
00385                                                         E->VOverZ               = OZ_FXP_TO_16_16 (     E->VOverZ               );
00386                                                         E->VOverZStep   = OZ_FXP_TO_16_16 (     E->VOverZStep   );
00387                                                 }
00388                                 }       
00389                 }
00390 }
00391 
00392 
00393 
00394 

Generated on Tue Sep 30 12:36:34 2003 for GTestAndEngine by doxygen 1.3.2