|
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) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.algorithms/16679e4d612e3.html, оценка из 5, голосов 10
|