1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- #include "System.h"
- #ifdef PATHS_IN_INCLUDES
- #include "GREEN/3D/render.h"
- #else
- #include "render.h"
- #endif
- typedef struct
- { RFixedS32 x; RFixedS32 y; RFixedS32 z;} RRenderPt32; // For internal use
- // Fog should be offset such that the first index occurs
- // at the minimum z-point of the full3d object being
- // rendered.
- // sX and sY are additional offsets into pimDst
- //
- void DrawTri_ZColorFog(UCHAR* pDstOffset,long lDstP,
- RP3d* p1,RP3d* p2,RP3d* p3,
- RZBuffer* pZB,UCHAR* pFog,
- short sOffsetX/* = 0*/, // In: 2D offset for pZB.
- short sOffsetY/* = 0*/) // In: 2D offset for pZB.
- {
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== INITIAL SET UP ========================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- // copy the 3d points into screen coordinates:
- RRenderPt32 pt1,pt2,pt3;
- RRenderPt32 *pv1 = &pt1;
- RRenderPt32 *pv2 = &pt2;
- RRenderPt32 *pv3 = &pt3;
- // Cast from REAL to short in fp32 format:
- pt1.x.mod = short(p1->x);
- pt1.y.mod = short(p1->y);
- pt1.z.mod = short(p1->z);
- pt2.x.mod = short(p2->x);
- pt2.y.mod = short(p2->y);
- pt2.z.mod = short(p2->z);
- pt3.x.mod = short(p3->x);
- pt3.y.mod = short(p3->y);
- pt3.z.mod = short(p3->z);
- pt1.x.frac =
- pt2.x.frac =
- pt3.x.frac = USHORT(32768); // offset each by 1/2
- /*
- // Catch the special case of a single pixel
- // This is really only useful for POSTAL TM, where polygons are tiny:
- if (pt1.x.mod == pt2.x.mod) // hierarchal check to save time:
- {
- if ( (pt1.y.mod == pt2.y.mod) // WE'VE GOT A SINGLE SCREEN POINT!
- && (pt1.x.mod == pt3.x.mod)
- && (pt1.y.mod == pt3.y.mod) )
- {
- // Try to best mimick normal behavior by using highest Z;
- // THIS will not exactly mimick the non-point cloud base,
- // but SHOULD work appropriately:
- if (pt2.z.mod > pt1.z.mod) pt1.z.mod = pt2.z.mod;
- if (pt3.z.mod > pt1.z.mod) pt1.z.mod = pt3.z.mod;
- //***** PLOT THE SINGLE POINT!
- short* pBufZ = pZB -> GetZPtr
- (pt1.x.mod + sOffsetX, pt1.y.mod + sOffsetY);
- if (pt1.z.mod > *pBufZ)
- {
- UCHAR* pDst = pDstOffset + lDstP * pt1.y.mod + pt1.x.mod;
- *pDst = pFog[pt1.z.upper]; // can't forget to set the z-buffer!
- *pBufZ = pt1.z.mod;
- }
- return; // DONE THE FAST WAY!
- }
- }
- */
- // Let's assess general categories:
- // Single points:
- /*
- short sAbort = TRUE;
- if (pt1.x.mod == pt2.x.mod)
- {
- if ( (pt1.y.mod == pt2.y.mod) // WE'VE GOT A SINGLE SCREEN POINT!
- && (pt1.x.mod == pt3.x.mod)
- && (pt1.y.mod == pt3.y.mod) )
- {
- // single point
- sAbort = FALSE;
- }
- }
- // Vertical strips:
- if ( (pt1.x.mod == pt2.x.mod)
- && (pt1.x.mod == pt3.x.mod) )
- {
- // Vstrip:
- sAbort = FALSE;
- }
- // Horizontal strips:
- if ( (pt1.y.mod == pt2.y.mod)
- && (pt1.y.mod == pt3.y.mod) )
- {
- // Hstrip:
- sAbort = FALSE;
- }
- if (sAbort == TRUE) return; // isolate the effect!
- */
- // Now let's try simply not drawing horiz or verical strips at all:
- // Vertical strips:
- /*
- if ( (pt1.x.mod == pt2.x.mod)
- && (pt1.x.mod == pt3.x.mod) )
- {
- // Vstrip or point:
- return;
- }
- // Horizontal strips:
- if ( (pt1.y.mod == pt2.y.mod)
- && (pt1.y.mod == pt3.y.mod) )
- {
- // Hstrip:
- return;
- }
- */
-
- // sort the triangles and choose which mirror case to render.
- // Sort points lowest to highest by y-value:
- if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
- if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
- if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
- // Get point 2 and 3's position relative to point 1:
- // Use 16 bit accuracy in y, 32-bit in x...
- short y1 = pv1->y.mod;
- short y2 = pv2->y.mod - y1;
- short y3 = pv3->y.mod - y1;
- short ybot = y3 - y2; // lower half delta
- if (y2 + y3 == 0) return; // don;t bother drawing horiz line
- // get relative floating point x coordinates: (32-bit differences)
- long fx1 = pv1->x.val;
- long fz1 = pv1->z.val;
- long fx2 = pv2->x.val - fx1;
- long fx3 = pv3->x.val - fx1;
- long fz2 = pv2->z.val - fz1;
- long fz3 = pv3->z.val - fz1;
- // calculate the top two edge slopes with 32-bit accuracy:
- long fx2inc,fz2inc;
- if (y2)
- {
- fx2inc = fx2 / y2; // stuck with division using fx32!
- fz2inc = fz2 / y2; // stuck with division using fx32!
- /* CANDIDATE FOR ONE_OVER!
- fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
- fz2inc = ULONG(fz2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
- */
- }
- long fx3inc = fx3 / y3; // stuck with division using fx32!
- long fz3inc = fz3 / y3; // stuck with division using fx32!
- // Set the two absolute edge positions
- RFixedS32 x2,x3,z2,z3;
- x2.val = x3.val = pv1->x.frac; // preserve floating point x!
- z2.val = z3.val = pv1->z.frac; // preserve floating point z!
- short sBaseZ = pv1->z.mod;
- //TRACE("SBASE Zpt = %hd\n",pv1->z.mod);
- long lP = lDstP;
- // add in extra piece uv rounding!
- UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
- short* pBufZ = pZB -> GetZPtr(pv1->x.mod + x2.mod + sOffsetX, pv1->y.mod + sOffsetY);
- long lZP = pZB->m_lP; // in words!!!
- // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
- short x,y;
- RFixedS32 fz,fzinc; // for tracing across each scan line:
- short xdel;
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== CHOOSE II CASES =======================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== FLAT TOP TRIANGLE =====================
- //****************************************************************
- // Don't worry about the wasted calculations above!
- // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
- // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
- if (y2 == 0) // p1.y == p2.y
- {
- long fx1inc,fz1inc;
- RFixedS32 x1,z1; // Absolute positions
- // Let point I be to the LEFT of point II:
- if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
- // again, set initial points relative to p1(0,0):
- fx1 = pv1->x.val;
- fz1 = pv1->z.val;
- fx2 = pv2->x.val - fx1;
- fx3 = pv3->x.val - fx1;
- fz2 = pv2->z.val - fz1;
- fz3 = pv3->z.val - fz1;
- sBaseZ = pv1->z.mod;
- // This time, we want the end slopes:
- //******* CANDIDATE FOR ONE_OVER!
- fx1inc = fx3 / y3; // from pt 1 to pt 3
- fz1inc = fz3 / y3;
- fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
- fz2inc = (fz3 - fz2) / y3; // from pt 2 to pt 3
- x1.val = pv1->x.frac; // preserve floating point x!
- x2.val = fx2;
- z1.val = pv1->z.frac; // preserve floating point x!
- z2.val = fz2; // preserve floating point z!
- pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
- pBufZ = pZB -> GetZPtr(pv1->x.mod + x1.mod + sOffsetX, pv1->y.mod + sOffsetY);
- for (y = y3;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x1.val += fx1inc;
- z2.val += fz2inc;
- z1.val += fz1inc;
- // Now we scan z across (slow for now)
- fz.val = z1.val;
- fz.mod += sBaseZ; // ****** advance the z-value.
- xdel = x2.mod - x1.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- //***************8 flipped the inc value:!
- if (xdel) fzinc.val = long(z2.mod - z1.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x1.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = pFog[fz.upper];// pFog[fz.upper]; // offset for fog
- *(pBufZ+x) = fz.mod; // set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- return;
- }
- //****************************************************************
- //====================== NORMAL TRIANGLE =======================
- //****************************************************************
- if (fx2inc <= fx3inc)
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- //TRACE("SBASE Z = %hd\n",sBaseZ);
- // Assume 2 to 3:
- // Now we scan z across (slow for now)
- fz.val = z2.val;
- fz.mod += sBaseZ; // This is for coloring but it effects true z as well!
- xdel = x3.mod - x2.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- if (xdel) fzinc.val = ULONG(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Now we scan z across (slow for now)
- fz.val = z2.val;
- fz.mod += sBaseZ;
- xdel = x3.mod - x2.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- if (xdel) fzinc.val = long(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- }
- }
- else // flip the x drawing order:
- //===================================================================
- //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
- //===================================================================
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Assume 2 to 3:
- // Now we scan z across (slow for now)
- fz.val = z3.val;
- fz.mod += sBaseZ;
- xdel = x2.mod - x3.mod; //+ x to z
- //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
- if (xdel) fzinc.val = long(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Now we scan z across (slow for now)
- fz.val = z3.val;
- fz.mod += sBaseZ;
- xdel = x2.mod - x3.mod;
- //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
- if (xdel) fzinc.val = ULONG(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
- // Full accuracy fxMul!
- //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- }
- }
- }
- //==================================================
- // For debugging:
- void DrawTri_wire(RImage* pimDst,short sX,short sY,
- RP3d* p1,RP3d* p2,RP3d* p3,UCHAR ucColor)
- {
- rspLine(ucColor,pimDst,
- sX+short(p1->x),sY+short(p1->y),
- sX+short(p2->x),sY+short(p2->y));
- rspLine(ucColor,pimDst,
- sX+short(p1->x),sY+short(p1->y),
- sX+short(p3->x),sY+short(p3->y));
- rspLine(ucColor,pimDst,
- sX+short(p3->x),sY+short(p3->y),
- sX+short(p2->x),sY+short(p2->y));
- }
- //==================================================
- // For debugging:
- // FLAT SHADED!
- // sX and sY are additional offsets into pimDst
- //
- void DrawTri_ZColor(UCHAR* pDstOffset,long lDstP,
- RP3d* p1,RP3d* p2,RP3d* p3,
- RZBuffer* pZB,UCHAR ucFlatColor,
- short sOffsetX/* = 0*/, // In: 2D offset for pZB.
- short sOffsetY/* = 0*/) // In: 2D offset for pZB.
- {
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== INITIAL SET UP ========================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- // copy the 3d points into screen coordinates:
- RRenderPt32 pt1,pt2,pt3;
- RRenderPt32 *pv1 = &pt1;
- RRenderPt32 *pv2 = &pt2;
- RRenderPt32 *pv3 = &pt3;
- // Cast from REAL to short in fp32 format:
- pt1.x.mod = short(p1->x);
- pt1.y.mod = short(p1->y);
- pt1.z.mod = short(p1->z);
- pt2.x.mod = short(p2->x);
- pt2.y.mod = short(p2->y);
- pt2.z.mod = short(p2->z);
- pt3.x.mod = short(p3->x);
- pt3.y.mod = short(p3->y);
- pt3.z.mod = short(p3->z);
- pt1.x.frac =
- pt2.x.frac =
- pt3.x.frac = USHORT(32768); // offset each by 1/2
-
- // sort the triangles and choose which mirror case to render.
- // Sort points lowest to highest by y-value:
- if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
- if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
- if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
- // Get point 2 and 3's position relative to point 1:
- // Use 16 bit accuracy in y, 32-bit in x...
- short y1 = pv1->y.mod;
- short y2 = pv2->y.mod - y1;
- short y3 = pv3->y.mod - y1;
- short ybot = y3 - y2; // lower half delta
- if (y2 + y3 == 0) return; // don;t bother drawing horiz line
- // get relative floating point x coordinates: (32-bit differences)
- long fx1 = pv1->x.val;
- long fz1 = pv1->z.val;
- long fx2 = pv2->x.val - fx1;
- long fx3 = pv3->x.val - fx1;
- long fz2 = pv2->z.val - fz1;
- long fz3 = pv3->z.val - fz1;
- // calculate the top two edge slopes with 32-bit accuracy:
- long fx2inc,fz2inc;
- if (y2)
- {
- fx2inc = fx2 / y2; // stuck with division using fx32!
- fz2inc = fz2 / y2; // stuck with division using fx32!
- /* CANDIDATE FOR ONE_OVER!
- fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
- fz2inc = ULONG(fz2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
- */
- }
- long fx3inc = fx3 / y3; // stuck with division using fx32!
- long fz3inc = fz3 / y3; // stuck with division using fx32!
- // Set the two absolute edge positions
- RFixedS32 x2,x3,z2,z3;
- x2.val = x3.val = pv1->x.frac; // preserve floating point x!
- z2.val = z3.val = pv1->z.frac; // preserve floating point z!
- short sBaseZ = pv1->z.mod;
- //TRACE("SBASE Zpt = %hd\n",pv1->z.mod);
- long lP = lDstP;
- // add in extra piece uv rounding!
- UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
- short* pBufZ = pZB -> GetZPtr(pv1->x.mod + x2.mod + sOffsetX, pv1->y.mod + sOffsetY);
- long lZP = pZB->m_lP; // in words!!!
- // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
- short x,y;
- RFixedS32 fz,fzinc; // for tracing across each scan line:
- short xdel;
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== CHOOSE II CASES =======================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== FLAT TOP TRIANGLE =====================
- //****************************************************************
- // Don't worry about the wasted calculations above!
- // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
- // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
- if (y2 == 0) // p1.y == p2.y
- {
- long fx1inc,fz1inc;
- RFixedS32 x1,z1; // Absolute positions
- // Let point I be to the LEFT of point II:
- if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
- // again, set initial points relative to p1(0,0):
- fx1 = pv1->x.val;
- fz1 = pv1->z.val;
- fx2 = pv2->x.val - fx1;
- fx3 = pv3->x.val - fx1;
- fz2 = pv2->z.val - fz1;
- fz3 = pv3->z.val - fz1;
- sBaseZ = pv1->z.mod;
- // This time, we want the end slopes:
- //******* CANDIDATE FOR ONE_OVER!
- fx1inc = fx3 / y3; // from pt 1 to pt 3
- fz1inc = fz3 / y3;
- fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
- fz2inc = (fz3 - fz2) / y3; // from pt 2 to pt 3
- x1.val = pv1->x.frac; // preserve floating point x!
- x2.val = fx2;
- z1.val = pv1->z.frac; // preserve floating point x!
- z2.val = fz2; // preserve floating point z!
- pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
- pBufZ = pZB -> GetZPtr(pv1->x.mod + x1.mod + sOffsetX, pv1->y.mod + sOffsetY);
- for (y = y3;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x1.val += fx1inc;
- z2.val += fz2inc;
- z1.val += fz1inc;
- // Now we scan z across (slow for now)
- fz.val = z1.val;
- fz.mod += sBaseZ; // ****** advance the z-value.
- xdel = x2.mod - x1.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- //***************8 flipped the inc value:!
- if (xdel) fzinc.val = long(z2.mod - z1.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x1.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = ucFlatColor;// pFog[fz.upper]; // offset for fog
- *(pBufZ+x) = fz.mod; // set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- return;
- }
- //****************************************************************
- //====================== NORMAL TRIANGLE =======================
- //****************************************************************
- if (fx2inc <= fx3inc)
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- //TRACE("SBASE Z = %hd\n",sBaseZ);
- // Assume 2 to 3:
- // Now we scan z across (slow for now)
- fz.val = z2.val;
- fz.mod += sBaseZ; // This is for coloring but it effects true z as well!
- xdel = x3.mod - x2.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- if (xdel) fzinc.val = ULONG(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = ucFlatColor;// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Now we scan z across (slow for now)
- fz.val = z2.val;
- fz.mod += sBaseZ;
- xdel = x3.mod - x2.mod;
- //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
- if (xdel) fzinc.val = long(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = ucFlatColor;// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- }
- }
- else // flip the x drawing order:
- //===================================================================
- //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
- //===================================================================
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Assume 2 to 3:
- // Now we scan z across (slow for now)
- fz.val = z3.val;
- fz.mod += sBaseZ;
- xdel = x2.mod - x3.mod; //+ x to z
- //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
- if (xdel) fzinc.val = long(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
- //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = ucFlatColor;// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- pBufZ += lZP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- z2.val += fz2inc;
- z3.val += fz3inc;
- // Now we scan z across (slow for now)
- fz.val = z3.val;
- fz.mod += sBaseZ;
- xdel = x2.mod - x3.mod;
- //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
- if (xdel) fzinc.val = ULONG(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
- // Full accuracy fxMul!
- //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++)
- {
- if (fz.mod > *(pBufZ+x) )
- {
- *(pDst+x) = ucFlatColor;// pFog[fz.upper];
- *(pBufZ+x) = fz.mod;// set Z-buffer!
- }
- fz.val += fzinc.val;
- }
- }
- }
- }
- }
- //==================================================
- // FLAT SHADED!
- // sX and sY are additional offsets into pimDst
- // There is NO Z_BUFFER here! It is JUST a polygon drawer
- //
- void DrawTri(UCHAR* pDstOffset,long lDstP,
- RP3d* p1,RP3d* p2,RP3d* p3,
- UCHAR ucFlatColor)
- {
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== INITIAL SET UP ========================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- // copy the 3d points into screen coordinates:
- RRenderPt32 pt1,pt2,pt3;
- RRenderPt32 *pv1 = &pt1;
- RRenderPt32 *pv2 = &pt2;
- RRenderPt32 *pv3 = &pt3;
- // Cast from REAL to short in fp32 format:
- pt1.x.mod = short(p1->x);
- pt1.y.mod = short(p1->y);
- pt2.x.mod = short(p2->x);
- pt2.y.mod = short(p2->y);
- pt3.x.mod = short(p3->x);
- pt3.y.mod = short(p3->y);
- pt1.x.frac =
- pt2.x.frac =
- pt3.x.frac = USHORT(32768); // offset each by 1/2
-
- // sort the triangles and choose which mirror case to render.
- // Sort points lowest to highest by y-value:
- if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
- if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
- if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
- // Get point 2 and 3's position relative to point 1:
- // Use 16 bit accuracy in y, 32-bit in x...
- short y1 = pv1->y.mod;
- short y2 = pv2->y.mod - y1;
- short y3 = pv3->y.mod - y1;
- short ybot = y3 - y2; // lower half delta
- if (y2 + y3 == 0) return; // don;t bother drawing horiz line
- // get relative floating point x coordinates: (32-bit differences)
- long fx1 = pv1->x.val;
- long fx2 = pv2->x.val - fx1;
- long fx3 = pv3->x.val - fx1;
- // calculate the top two edge slopes with 32-bit accuracy:
- long fx2inc;
- if (y2)
- {
- fx2inc = fx2 / y2; // stuck with division using fx32!
- /* CANDIDATE FOR ONE_OVER!
- fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
- */
- }
- long fx3inc = fx3 / y3; // stuck with division using fx32!
- // Set the two absolute edge positions
- RFixedS32 x2,x3;
- x2.val = x3.val = pv1->x.frac; // preserve floating point x!
- long lP = lDstP;
- // add in extra piece uv rounding!
- UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
- // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
- short x,y;
- short xdel;
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== CHOOSE II CASES =======================
- //****************************************************************
- //////////////////////////////////////////////////////////////////
- //****************************************************************
- //====================== FLAT TOP TRIANGLE =====================
- //****************************************************************
- // Don't worry about the wasted calculations above!
- // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
- // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
- if (y2 == 0) // p1.y == p2.y
- {
- long fx1inc;
- RFixedS32 x1; // Absolute positions
- // Let point I be to the LEFT of point II:
- if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
- // again, set initial points relative to p1(0,0):
- fx1 = pv1->x.val;
- fx2 = pv2->x.val - fx1;
- fx3 = pv3->x.val - fx1;
- // This time, we want the end slopes:
- //******* CANDIDATE FOR ONE_OVER!
- fx1inc = fx3 / y3; // from pt 1 to pt 3
- fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
- x1.val = pv1->x.frac; // preserve floating point x!
- x2.val = fx2;
- pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
- for (y = y3;y;y--)
- {
- pDst += lP;
- x2.val += fx2inc;
- x1.val += fx1inc;
- xdel = x2.mod - x1.mod;
- //***************8 flipped the inc value:!
- // Assume 2 to 3:
- for (x = x1.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
- }
- return;
- }
- //****************************************************************
- //====================== NORMAL TRIANGLE =======================
- //****************************************************************
- if (fx2inc <= fx3inc)
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- // Assume 2 to 3:
- xdel = x3.mod - x2.mod;
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++) *(pDst+x) = ucFlatColor;
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- xdel = x3.mod - x2.mod;
- // Assume 2 to 3:
- for (x = x2.mod; x<= x3.mod;x++) *(pDst+x) = ucFlatColor;
- }
- }
- }
- else // flip the x drawing order:
- //===================================================================
- //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
- //===================================================================
- {
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
- for (y = y2;y;y--)
- {
- pDst += lP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- // Assume 2 to 3:
- xdel = x2.mod - x3.mod; //+ x to z
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
- }
- //===================================================================
- // Draw the lower triangle if applicatable:
- //===================================================================
- if (ybot)
- {
- // new x2 slope:
- fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
- /*
- fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
- */
- //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
- for (y = ybot;y;y--)
- {
- pDst += lP;
- x2.val += fx2inc;
- x3.val += fx3inc;
- xdel = x2.mod - x3.mod;
- // Full accuracy fxMul!
- // Assume 2 to 3:
- for (x = x3.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
- }
- }
- }
- }
|