Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Alexei Frounze                       2:5020/400     28 May 2001  23:04:12
 To : Oleg Tynianyi
 Subject : Re: текстурирование (сырэц)
 -------------------------------------------------------------------------------- 
 
 Mon May 28 2001 10:22, Oleg Tynianyi wrote to All:
 
  >> Если нужен вариант исходника на чистом си, могу запостить.
 
  OT> И мне запость плиз !
 
 Приблизительно так:
 
 /***************************************************/
 /* Written by Alexei A. Frounze on                 */
 /*                  12 of jan  1999 ... 5 mar 2000 */
 /*                                                 */
 /* Compiler: DJGPP 2.95.2                          */
 /*                                                 */
 /* E-mail  : alexfru@chat.ru                       */
 /* Homepage: http://www.chat.ru/~alexfru           */
 /*           http://members.xoom.com/alexfru       */
 /***************************************************/
 
 // See Mark Feldman's article about texture mapping:
 // "http://www.geocities.com/SiliconValley/2151"
 // and Mikael Kalms' article about texture mapping:
 // "http://www.lysator.liu.se/~mikaelk/doc/perspectivetexture/"
 
 #include <math.h>
 
 #include "defs.h"
 #include "tmapping.h"
 #include "vectors.h"
 #include "pstack.h"
 #include "grafix.h"
 #include "misc.h"
 
 int     KP=256;
 int     SUB_BITS=4, SUB_CNT=16;
 double  ZClose = 0.01, IZClose = 100.0;
 int     Window_Width=320, Window_Height=200,
         Window_Center_X=160, Window_Center_Y=100;
 
 #define NO_DISTORSION
 #define y2addr(y)       (y*Window_Width)
 
 extern void span (char *scr, char *txt, int n,
                   int u, int v, int du, int dv);
 
                         /* ORIGINAL POLYGON DATA */
 
 // Number of polygon vertices
 int     VCNT;
 // Verices of a polygon in a 3d space
 Vector  Vertices[Max_Edges+1];
 // Appropriate u and v values
 double  tu[Max_Edges+1], tv[Max_Edges+1];
 
                         /* TEMPORARY POLYGON DATA */
 
 // Number of Vertices at the screen
 int     _VCNT;
 // Clipped polygon Vertices
 Vector  _Vertices[Max_Edges+1];
 // Appropriate u and v values
 double  _tu[Max_Edges+1], _tv[Max_Edges+1];
 // Screen verices of a polygon
 double  XR[Max_Edges+1], YR[Max_Edges+1];
 // Buffers for projecting a polygon. Left & right screen boundaries:
 int     Scan_Buf_L[480], Scan_Buf_R[480];
 double  inv_z_L[480], u_div_z_L[480], v_div_z_L[480];
 double  inv_z_R[480], u_div_z_R[480], v_div_z_R[480];
 double  Scan_Buf_L2[480], Scan_Buf_R2[480];
 
                         /* OTHER VARIABLES */
 
 // Minimal & maximal screen X and Y (integer) of a polygon:
 int     YminI, YmaxI, XminI, XmaxI;
 
 // Boolean array for tmapper. It is used to clip polygons with
 // Z=ZClose plain
 int Behind[Max_Edges+1];
 
 // Linear interpolation choosing (0=none,1=16pxls)
 int SubDiv=1;
 
                         /* FUNCTIONS */
 
 // This one finds screen min & max X for each Y of polgon's edge
 void Scan_Edge (int N) {
   double X, DX;
   int IsLeftEdge;
   double X1R, Y1R, X2R, Y2R;
   int Y1I, Y2I, /*XI,*/ YI;
 
   double iz1, iz2, uz1, uz2, vz1, vz2;
   double iz, uz, vz, diz, duz, dvz;
   double ddd;
   int M;
 //  short  SW, LW = 0x1B3F;
 
   M = (N+1)%_VCNT;
 
   X1R = XR[N]; Y1R = YR[N];
   iz1 = (double)1/_Vertices[N].Z;
   uz1 = _tu[N] * iz1;
   vz1 = _tv[N] * iz1;
 
   X2R = XR[M]; Y2R = YR[M];
   iz2 = (double)1/_Vertices[M].Z;
   uz2 = _tu[M] * iz2;
   vz2 = _tv[M] * iz2;
 
   IsLeftEdge = Y2R < Y1R;
 
   ddd = 1.0 / (Y1R - Y2R);
   DX  = (X1R - X2R) * ddd;
   diz = (iz1 - iz2) * ddd;
   duz = (uz1 - uz2) * ddd;
   dvz = (vz1 - vz2) * ddd;
 
   if (IsLeftEdge) {
     Y2I = (int)ceil(Y2R); Y1I = (int)ceil(Y1R)-1;
     if (Y2I > Y1I) return;
     ddd = Y2I - Y2R;
     X  = X2R + ddd * DX;
     iz = iz2 + ddd * diz;
     uz = uz2 + ddd * duz;
     vz = vz2 + ddd * dvz;
     YI = Y1I; Y1I = Y2I; Y2I = YI;
   } else {
     Y1I = (int)ceil(Y1R); Y2I = (int)ceil(Y2R)-1;
     if (Y1I > Y2I) return;
     ddd = Y1I - Y1R;
     X  = X1R + ddd * DX;
     iz = iz1 + ddd * diz;
     uz = uz1 + ddd * duz;
     vz = vz1 + ddd * dvz;
   };
 
   if (Y1I < 0) {
     X  -= Y1I*DX;
     iz -= Y1I*diz;
     uz -= Y1I*duz;
     vz -= Y1I*dvz;
     Y1I = 0;
   };
   if (Y2I > Window_Height-1)
     Y2I = Window_Height-1;
 
   if (IsLeftEdge)
     for (YI=Y1I;YI<=Y2I;YI++) {
 
       Scan_Buf_L2[YI] = X;
       Scan_Buf_L[YI] = (int)ceil(X);
       X += DX;
 
       inv_z_L[YI] = iz;
       iz += diz;
       u_div_z_L[YI] = uz;
       uz += duz;
       v_div_z_L[YI] = vz;
       vz += dvz;
     }
    else
     for (YI=Y1I;YI<=Y2I;YI++) {
 
       Scan_Buf_R2[YI] = X;
       Scan_Buf_R[YI] = (int)ceil(X);
       X += DX;
 
       inv_z_R[YI] = iz;
       iz += diz;
       u_div_z_R[YI] = uz;
       uz += duz;
       v_div_z_R[YI] = vz;
       vz += dvz;
     };
 }
 
 /**********************************/
 /* MAIN TEXTURE MAPPING FUNCTIONS */
 /**********************************/
 
 // Maps a texture onto an arbitrary polygon
 void T_Map (char *texture) {
   double NX, NY, IZ;
   int IndexMin, IndexMax, IndexMinX, IndexMaxX, i, k;
   int xl, xr;
   double uz, vz, duz, dvz;
   double iz, diz;
   int u, v;
   int zzz;
   char *scr;
   double iiz;
   int u1, v1, u2, v2, du, dv, n;
   int tmp1, tmp2;
   int CONST = 1 << 16;
   double sss, sss2;
   double diz2, duz2, dvz2;
   int CONST2;
 
   for(i=0;i<VCNT;i++)
     Behind[i] = (Vertices[i].Z < ZClose);
 
   _VCNT=0;
   for (i=0;i<VCNT;i++) {
     if (!Behind[i]) {
       IZ = (double)1/ Vertices[i].Z;
       XR[_VCNT] = Vertices[i].X * IZ;
       YR[_VCNT] = Vertices[i].Y * IZ;
       _Vertices[_VCNT] = Vertices[i];
       _tu[_VCNT] = tu[i];
       _tv[_VCNT] = tv[i];
       _VCNT++;
     };
     k = (i+1)%VCNT;
     if (Behind[i] != Behind[k]) {
       IZ = (ZClose-Vertices[i].Z) / (Vertices[k].Z-Vertices[i].Z);
       NX = Vertices[i].X + (Vertices[k].X-Vertices[i].X) * IZ;
       NY = Vertices[i].Y + (Vertices[k].Y-Vertices[i].Y) * IZ;
       XR[_VCNT] = NX / ZClose;
       YR[_VCNT] = NY / ZClose;
       _Vertices[_VCNT].X = NX;
       _Vertices[_VCNT].Y = NY;
       _Vertices[_VCNT].Z = ZClose;
       _tu[_VCNT] = tu[i] + (tu[k]-tu[i]) * IZ;
       _tv[_VCNT] = tv[i] + (tv[k]-tv[i]) * IZ;
       _VCNT++;
     };
   };
 
   if (_VCNT < 3) return;
 
   // Computing XR[] and YR[] screen TVertices for a polygon
 
   for (i=0;i<_VCNT;i++) {
     XR[i] *= KP; XR[i] += Window_Center_X;
     YR[i] *= KP; YR[i] += Window_Center_Y;
   };
 
   // Done. Computing minimal Y and maximal Y at screen for a polygon
 
   IndexMin = IndexMax = IndexMinX = IndexMaxX = 0;
   for (i=0;i<_VCNT;i++) {
     if (YR[i] < YR[IndexMin]) IndexMin = i;
     if (YR[i] > YR[IndexMax]) IndexMax = i;
     if (XR[i] < XR[IndexMinX]) IndexMinX = i;
     if (XR[i] > XR[IndexMaxX]) IndexMaxX = i;
   };
 
   // Getting integer values of min Y and max Y
 
   YminI = (int)ceil(YR[IndexMin]);
   YmaxI = (int)ceil(YR[IndexMax])-1;
   XminI = (int)ceil(XR[IndexMinX]);
   XmaxI = (int)ceil(XR[IndexMaxX])-1;
 
   // Is polygon visible at screen?
 
   if ((YminI > YmaxI) || (XminI > XmaxI)) return;
   tmp1 = Boundaries[SSP-1].Ymin;
   tmp2 = Boundaries[SSP-1].Ymax;
 
   if ((YminI > tmp2) || (YmaxI < tmp1) ||
      (XminI > Boundaries[SSP-1].Xmax) ||
      (XmaxI < Boundaries[SSP-1].Xmin)) return;
 
   if (YminI < tmp1) YminI = tmp1;
   if (YmaxI > tmp2) YmaxI = tmp2;
 
   // It's visible. Finding left and right screen boundaries per each y-line.
   // It's done for all edges of a polygon
 
   for (i=0;i<_VCNT;i++)
     Scan_Edge (i);
 
   for (i=YminI;i<=YmaxI;i++) {
     xl=Scan_Buf_L[i];
     xr=Scan_Buf_R[i]-1;
     if (xl > xr) continue;
     if ((xl>=Window_Width) || (xr<0)) continue;
 
     tmp1 = (int)Boundaries[SSP-1].bounds[i][0];
     tmp2 = (int)Boundaries[SSP-1].bounds[i][1];
     if ((tmp1 > tmp2) || (xl > tmp2) || (xr < tmp1)) continue;
 
     iz = inv_z_L[i];
     uz = u_div_z_L[i];
     vz = v_div_z_L[i];
 
     sss = (double)1/(Scan_Buf_R2[i]-Scan_Buf_L2[i]);
     diz = (inv_z_R[i] - iz) * sss;
     duz = (u_div_z_R[i] - uz) * sss;
     dvz = (v_div_z_R[i] - vz) * sss;
 
     sss2 = xl - Scan_Buf_L2[i];
     iz += diz * sss2;
     uz += duz * sss2;
     vz += dvz * sss2;
 
     if (xl < tmp1) {
       int ttt=tmp1-xl;
 
       iz += diz*ttt;
       uz += duz*ttt;
       vz += dvz*ttt;
 
       xl = tmp1;
     };
     if (xr > tmp2) xr = tmp2;
 
     zzz = xr-xl+1;
     scr = VGAAddr + xl + y2addr (i);
 
     diz2 = diz;
     duz2 = duz;
     dvz2 = dvz;
 
 if (SubDiv) {
 #ifdef NO_DISTORSION
     CONST2 = (SUB_CNT - (xl & (SUB_CNT-1))) & (SUB_CNT-1);
     if (CONST2) {
       diz *= CONST2;
       duz *= CONST2;
       dvz *= CONST2;
     } else {
       diz *= SUB_CNT;
       duz *= SUB_CNT;
       dvz *= SUB_CNT;
     };
 #else
     diz *= SUB_CNT;
     duz *= SUB_CNT;
     dvz *= SUB_CNT;
 #endif
 
     iiz = CONST / iz;
     u1 = (int)(uz * iiz);
     v1 = (int)(vz * iiz);
 
     iz += diz;
     uz += duz;
     vz += dvz;
 
     iiz = CONST / iz;
     u2 = (int)(uz * iiz);
     v2 = (int)(vz * iiz);
 
     du = u2 - u1;
     dv = v2 - v1;
 #ifdef NO_DISTORSION
     if (!CONST2) {
       du>>=SUB_BITS;
       dv>>=SUB_BITS;
     } else {
       du /= CONST2;
       dv /= CONST2;
 
       diz = diz2*SUB_CNT;
       duz = duz2*SUB_CNT;
       dvz = dvz2*SUB_CNT;
     };
 #else
 
     du>>=SUB_BITS;
     dv>>=SUB_BITS;
 
 #endif
     while (1) {
 #ifdef NO_DISTORSION
       if (CONST2) {
         n = CONST2;
         zzz -= CONST2;
         CONST2=0;
       } else {
         n = SUB_CNT;
         zzz -= SUB_CNT;
       };
 #else
       n = SUB_CNT;
       zzz -= SUB_CNT;
 #endif
       if (zzz<0) n+=zzz;
 
       if (zzz) {
         iz += diz;
         iiz = CONST / iz;
       };
 
 //      span (scr, texture, n, u1, v1, du, dv);
 
       while (n--) {
         *scr++ = texture[((v1>>8)&0xFF00)+((u1>>16)&0xFF)];
         u1+=du;
         v1+=dv;
       }
 
       if (zzz<=0)
         break;
 
 //      scr += n;
 
       u1 = u2;
       v1 = v2;
       uz += duz;
       vz += dvz;
 
       u2 = (int)(uz * iiz);
       v2 = (int)(vz * iiz);
 
       du = (u2 - u1) >> SUB_BITS;
       dv = (v2 - v1) >> SUB_BITS;
     };
 } else {
     while (zzz--) {
       u = ((int)(uz / iz))&255;
       v = ((int)(vz / iz))&255;
       *scr++ = *(texture+(v<<8)+u);
       iz += diz;
       uz += duz;
       vz += dvz;
     };
 };
   };
 }
 
 http://alexfru.chat.ru
 
 --- ifmail v.2.15dev5
  * Origin: FidoNet Online - http://www.fido-online.com (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Re: текстурирование (сырэц)   Alexei Frounze   28 May 2001 23:04:12 
Архивное /ru.algorithms/16679e4d612e3.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional