You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
948 lines
23 KiB
948 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name
|
|
|
|
trimesh.cxx
|
|
|
|
Abstract:
|
|
|
|
Implement triangle mesh API
|
|
|
|
Author:
|
|
|
|
Mark Enstrom (marke) 23-Jun-1996
|
|
|
|
Enviornment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#include "dciman.h"
|
|
#pragma hdrstop
|
|
|
|
#if !(_WIN32_WINNT >= 0x500)
|
|
|
|
//
|
|
// temp global
|
|
//
|
|
|
|
HBITMAP hbmDefault;
|
|
|
|
|
|
#if DBG
|
|
ULONG DbgRecord = 0;
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vHorizontalLine
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 11/20/1996 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
inline
|
|
VOID
|
|
vHorizontalLine(
|
|
PTRIVERTEX pv1,
|
|
PTRIVERTEX pv2,
|
|
PTRIANGLEDATA ptData,
|
|
PTRIDDA ptridda
|
|
)
|
|
{
|
|
LONG yPosition = ptridda->N0 >> 4;
|
|
LONG yIndex = yPosition - ptData->rcl.top;
|
|
|
|
ptridda->L = ptridda->M0 >> 4;
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vCalculateLine:Horizontal Line: L = 0x%lx, yIndex = 0x%lx\n",ptridda->L,yIndex);
|
|
}
|
|
#endif
|
|
|
|
|
|
if ((yPosition >= ptData->rcl.top) &&
|
|
(yPosition < ptData->rcl.bottom))
|
|
{
|
|
//
|
|
// find left edge
|
|
//
|
|
|
|
if (pv1->x <= pv2->x)
|
|
{
|
|
//
|
|
// left edge
|
|
// !!! is the check necessary? overlap from another
|
|
// line segment.
|
|
//
|
|
|
|
ptData->TriEdge[yIndex].xLeft = pv1->x >> 4;
|
|
ptData->TriEdge[yIndex].Red = pv1->Red << 8;
|
|
ptData->TriEdge[yIndex].Green = pv1->Green << 8;
|
|
ptData->TriEdge[yIndex].Blue = pv1->Blue << 8;
|
|
ptData->TriEdge[yIndex].Alpha = pv1->Alpha << 8;
|
|
|
|
//
|
|
// right edge
|
|
//
|
|
|
|
ptData->TriEdge[yIndex].xRight = pv2->x >> 4;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// left edge
|
|
//
|
|
|
|
ptData->TriEdge[yIndex].xLeft = pv2->x >> 4;
|
|
ptData->TriEdge[yIndex].Red = pv2->Red << 8;
|
|
ptData->TriEdge[yIndex].Green = pv2->Green << 8;
|
|
ptData->TriEdge[yIndex].Blue = pv2->Blue << 8;
|
|
ptData->TriEdge[yIndex].Alpha = pv2->Alpha << 8;
|
|
|
|
//
|
|
// right edge
|
|
//
|
|
|
|
ptData->TriEdge[yIndex].xRight = pv1->x >> 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vLeftEdgeDDA
|
|
*
|
|
* Run line DDA down a left edge of the triangle recording left edge
|
|
* position and color
|
|
*
|
|
* Arguments:
|
|
*
|
|
* NumScanLines
|
|
* yIndex
|
|
* Red
|
|
* Green
|
|
* Blue
|
|
* Alpha
|
|
* L
|
|
* Rb
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
* History:
|
|
*
|
|
* 11/20/1996 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
inline
|
|
VOID
|
|
vLeftEdgeDDA(
|
|
PTRIANGLEDATA ptData,
|
|
PTRIDDA ptridda
|
|
)
|
|
{
|
|
LONG NumScanLines = ptridda->NumScanLines;
|
|
LONG yIndex = ptridda->yIndex;
|
|
LONG Red = ptridda->Red;
|
|
LONG Green = ptridda->Green;
|
|
LONG Blue = ptridda->Blue;
|
|
LONG Alpha = ptridda->Alpha;
|
|
LONG L = ptridda->L;
|
|
LONG Rb = ptridda->Rb;
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vLeftEdgeDDA:Scan yIndex = %li\n",yIndex);
|
|
}
|
|
#endif
|
|
|
|
// Scan all lines, only record lines contained by
|
|
// the clipping in ptData->rcl (y)
|
|
|
|
while (NumScanLines--)
|
|
{
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 3)
|
|
{
|
|
DbgPrint("vCalculateLine:Scan yIndex = %li\n",yIndex);
|
|
DbgPrint("vCalculateLine:L = %li\n",L);
|
|
DbgPrint("vCalculateLine:Rb = %li\n",Rb);
|
|
}
|
|
#endif
|
|
|
|
// record left edge
|
|
|
|
if (yIndex >= 0)
|
|
{
|
|
ptData->TriEdge[yIndex].xLeft = L;
|
|
ptData->TriEdge[yIndex].Red = Red;
|
|
ptData->TriEdge[yIndex].Green = Green;
|
|
ptData->TriEdge[yIndex].Blue = Blue;
|
|
ptData->TriEdge[yIndex].Alpha = Alpha;
|
|
}
|
|
|
|
// inc y by one scan line, inc x(L) by integer step
|
|
// and inc error term by dR
|
|
|
|
yIndex++;
|
|
L += ptridda->dL;
|
|
Rb -= ptridda->dR;
|
|
|
|
// inc color components by y and integer x components
|
|
|
|
Red += (ptridda->dxyRed);
|
|
Green += (ptridda->dxyGreen);
|
|
Blue += (ptridda->dxyBlue);
|
|
Alpha += (ptridda->dxyAlpha);
|
|
|
|
// check for DDA error term overflow, add one
|
|
// more step in x if true, and correct error term
|
|
|
|
if (Rb < 0)
|
|
{
|
|
// DDA
|
|
|
|
L += ptridda->Linc;
|
|
Rb += ptridda->dN;
|
|
|
|
// inc color components
|
|
|
|
Red += ptData->dRdX;
|
|
Green += ptData->dGdX;
|
|
Blue += ptData->dBdX;
|
|
Alpha += ptData->dAdX;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vRightEdgeDDA
|
|
*
|
|
* Run the line DDA along the right edge of the triangle recording right
|
|
* edge position
|
|
*
|
|
* Arguments:
|
|
*
|
|
* NumScanLines
|
|
* yIndex
|
|
* Red
|
|
* Green
|
|
* Blue
|
|
* Alpha
|
|
* L
|
|
* Rb
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
* History:
|
|
*
|
|
* 11/25/1996 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
inline
|
|
VOID
|
|
vRightEdgeDDA(
|
|
PTRIANGLEDATA ptData,
|
|
PTRIDDA ptridda
|
|
)
|
|
{
|
|
LONG NumScanLines = ptridda->NumScanLines;
|
|
LONG yIndex = ptridda->yIndex;
|
|
LONG Red = ptridda->Red;
|
|
LONG Green = ptridda->Green;
|
|
LONG Blue = ptridda->Blue;
|
|
LONG Alpha = ptridda->Alpha;
|
|
LONG L = ptridda->L;
|
|
LONG Rb = ptridda->Rb;
|
|
|
|
// Scan all lines, only record lines contained by
|
|
// the clipping in ptData->rcl (y)
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vRightEdgeDDA:Scan yIndex = %li\n",yIndex);
|
|
}
|
|
#endif
|
|
|
|
while (ptridda->NumScanLines--)
|
|
{
|
|
#if DBG
|
|
if (DbgRecord >= 3)
|
|
{
|
|
DbgPrint("vCalculateLine:Scan yIndex = %li\n",yIndex);
|
|
DbgPrint("vCalculateLine:L = %li\n",L);
|
|
DbgPrint("vCalculateLine:Rb = %li\n",Rb);
|
|
}
|
|
#endif
|
|
|
|
// record left, right edge
|
|
|
|
if (yIndex >= 0)
|
|
{
|
|
ptData->TriEdge[yIndex].xRight = L;
|
|
}
|
|
|
|
// inc y by one scan line, inc x(L) by integer step
|
|
// and inc error term by dR
|
|
|
|
yIndex++;
|
|
L += ptridda->dL;
|
|
Rb -= ptridda->dR;
|
|
|
|
// inc color components by y and integer x components
|
|
|
|
Red += (ptridda->dxyRed);
|
|
Green += (ptridda->dxyGreen);
|
|
Blue += (ptridda->dxyBlue);
|
|
Alpha += (ptridda->dxyAlpha);
|
|
|
|
// check for DDA error term overflow, add one
|
|
// more step in x if true, and correct error term
|
|
|
|
if (Rb < 0)
|
|
{
|
|
// DDA
|
|
|
|
L += ptridda->Linc;
|
|
Rb += ptridda->dN;
|
|
|
|
// inc color components
|
|
|
|
Red += ptData->dRdX;
|
|
Green += ptData->dGdX;
|
|
Blue += ptData->dBdX;
|
|
Alpha += ptData->dAdX;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vCalulateLine
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 11/20/1996 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vCalculateLine(
|
|
PTRIVERTEX pv1,
|
|
PTRIVERTEX pv2,
|
|
PTRIANGLEDATA ptData,
|
|
BOOL bLeftEdge
|
|
)
|
|
{
|
|
TRIDDA tridda;
|
|
|
|
//
|
|
// initial y component
|
|
//
|
|
|
|
tridda.dxyRed = ptData->dRdY;
|
|
tridda.dxyGreen = ptData->dGdY;
|
|
tridda.dxyBlue = ptData->dBdY;
|
|
tridda.dxyAlpha = ptData->dAdY;
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vCalculateLine:\n");
|
|
DbgPrint("vCalculateLine:pv1.x = %li, pv1.y = %li\n",pv1->x,pv1->y);
|
|
DbgPrint("vCalculateLine:pv1->Red = 0x%lx, pv1->Green = 0x%lx, pv1->Blue = 0x%lx\n",
|
|
pv1->Red,pv1->Green,pv1->Blue);
|
|
DbgPrint("vCalculateLine:pv2.x = %li, pv2.y = %li\n",pv2->x,pv2->y);
|
|
DbgPrint("vCalculateLine:pv2->Red = 0x%lx, pv2->Green = 0x%lx, pv2->Blue = 0x%lx\n",
|
|
pv2->Red,pv2->Green,pv2->Blue);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Arrange lines, must run in positive delta y.
|
|
// !!! what other effect of swap is there? !!!
|
|
//
|
|
|
|
if (pv2->y >= pv1->y)
|
|
{
|
|
tridda.dN = pv2->y - pv1->y;
|
|
tridda.dM = pv2->x - pv1->x;
|
|
tridda.N0 = pv1->y;
|
|
tridda.M0 = pv1->x;
|
|
tridda.Red = pv1->Red << 8;
|
|
tridda.Green = pv1->Green << 8;
|
|
tridda.Blue = pv1->Blue << 8;
|
|
tridda.Alpha = pv1->Alpha << 8;
|
|
}
|
|
else
|
|
{
|
|
tridda.dN = pv1->y - pv2->y;
|
|
tridda.dM = pv1->x - pv2->x;
|
|
tridda.N0 = pv2->y;
|
|
tridda.M0 = pv2->x;
|
|
tridda.Red = pv2->Red << 8;
|
|
tridda.Green = pv2->Green << 8;
|
|
tridda.Blue = pv2->Blue << 8;
|
|
tridda.Alpha = pv2->Alpha << 8;
|
|
tridda.dxyRed = -tridda.dxyRed;
|
|
tridda.dxyGreen = -tridda.dxyGreen;
|
|
tridda.dxyBlue = -tridda.dxyBlue;
|
|
tridda.dxyAlpha = -tridda.dxyAlpha;
|
|
}
|
|
|
|
//
|
|
// Check for horizontal line, dN == 0 is a horizontal line.
|
|
// In this case just record the end points.
|
|
//
|
|
|
|
if (tridda.dN == 0)
|
|
{
|
|
vHorizontalLine(pv1,pv2,ptData,&tridda);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// this is as cryptic as ASM at the moment
|
|
//
|
|
|
|
LONG l0,Frac;
|
|
|
|
tridda.Linc = 1;
|
|
|
|
//
|
|
// yIndex is the offset into the edge array for
|
|
// the current line
|
|
//
|
|
|
|
tridda.yIndex = (tridda.N0 >> 4) - ptData->y0;
|
|
|
|
tridda.NumScanLines = (tridda.dN >> 4);
|
|
|
|
LONG NMax = (tridda.N0 >> 4) + tridda.NumScanLines;
|
|
|
|
//
|
|
// make sure scan lines do not overrun buffer due to
|
|
// clipping
|
|
//
|
|
|
|
if (
|
|
((tridda.N0 >> 4) > ptData->rcl.bottom) ||
|
|
(NMax < ptData->rcl.top)
|
|
)
|
|
{
|
|
// nothing to draw
|
|
return;
|
|
}
|
|
else if (NMax > ptData->rcl.bottom)
|
|
{
|
|
tridda.NumScanLines = tridda.NumScanLines - (NMax - ptData->rcl.bottom);
|
|
}
|
|
|
|
tridda.j = tridda.N0 >> 4;
|
|
|
|
tridda.C = ((LONGLONG)tridda.M0 * (LONGLONG)tridda.dN) - ((LONGLONG)tridda.N0 * (LONGLONG)tridda.dM) -1;
|
|
|
|
tridda.C = (tridda.C >> 4) + tridda.dN;
|
|
|
|
LONGLONG LongL;
|
|
|
|
if (tridda.dM > 0)
|
|
{
|
|
tridda.dL = tridda.dM / tridda.dN;
|
|
tridda.dR = tridda.dM - tridda.dL * tridda.dN;
|
|
}
|
|
else if (tridda.dM < 0)
|
|
{
|
|
// negative divide
|
|
|
|
LONG dLQ,dLR;
|
|
|
|
tridda.dM = -tridda.dM;
|
|
|
|
dLQ = (tridda.dM - 1) / tridda.dN;
|
|
dLR = tridda.dM - 1 - (dLQ * tridda.dN);
|
|
tridda.dL = -(dLQ + 1);
|
|
tridda.dR = tridda.dN - dLR - 1;
|
|
}
|
|
else
|
|
{
|
|
// dM = 0
|
|
tridda.dL = 0;
|
|
tridda.dR = 0;
|
|
}
|
|
|
|
l0 = tridda.j * tridda.dL;
|
|
LongL = tridda.j * tridda.dR + tridda.C;
|
|
|
|
if (LongL > 0)
|
|
{
|
|
Frac = (LONG)(LongL/tridda.dN); // integer portion
|
|
}
|
|
else if (LongL < 0)
|
|
{
|
|
LONG Q = (LONG)((-LongL - 1)/tridda.dN);
|
|
Frac = -(Q + 1);
|
|
}
|
|
else
|
|
{
|
|
Frac = 0;
|
|
}
|
|
|
|
tridda.R = (LONG)(LongL - (Frac * tridda.dN));
|
|
tridda.L = l0 + Frac;
|
|
tridda.Rb = tridda.dN - tridda.R - 1;
|
|
|
|
//
|
|
// Calculate color steps for dx !!! could it be more expensive !!!
|
|
//
|
|
|
|
if (tridda.dL != 0)
|
|
{
|
|
tridda.dxyRed = tridda.dxyRed + (LONG)((ptData->dRdXA * tridda.dL) / ptData->Area);
|
|
tridda.dxyGreen = tridda.dxyGreen + (LONG)((ptData->dGdXA * tridda.dL) / ptData->Area);
|
|
tridda.dxyBlue = tridda.dxyBlue + (LONG)((ptData->dBdXA * tridda.dL) / ptData->Area);
|
|
tridda.dxyAlpha = tridda.dxyAlpha + (LONG)((ptData->dAdXA * tridda.dL) / ptData->Area);
|
|
}
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
LONG CL = (LONG)tridda.C;
|
|
LONG CH = (LONG)(tridda.C/4294967296);
|
|
DbgPrint("vCalculateLine:Normal Line\n");
|
|
DbgPrint("vCalculateLine:N0 = %li\n",tridda.N0);
|
|
DbgPrint("vCalculateLine:dN = %li\n",tridda.dN);
|
|
DbgPrint("vCalculateLine:M0 = %li\n",tridda.M0);
|
|
DbgPrint("vCalculateLine:dM = %li\n",tridda.dM);
|
|
DbgPrint("vCalculateLine:C = %08lx %08lx\n",CH,CL);
|
|
DbgPrint("vCalculateLine:Frac = %li\n",Frac);
|
|
DbgPrint("vCalculateLine:l0 = %li\n",l0);
|
|
DbgPrint("vCalculateLine:L = %li\n",tridda.L);
|
|
DbgPrint("vCalculateLine:dL = %li\n",tridda.dL);
|
|
DbgPrint("vCalculateLine:R = %li\n",tridda.R);
|
|
DbgPrint("vCalculateLine:dR = %li\n",tridda.dR);
|
|
DbgPrint("vCalculateLine:Rb = %li\n",tridda.Rb);
|
|
DbgPrint("vCalculateLine:dxyRed = 0x%lx\n",tridda.dxyRed);
|
|
DbgPrint("vCalculateLine:dxyGreen = 0x%lx\n",tridda.dxyGreen);
|
|
DbgPrint("vCalculateLine:dxyBlue = 0x%lx\n",tridda.dxyBlue);
|
|
DbgPrint("vCalculateLine:dxyAlpha = 0x%lx\n",tridda.dxyAlpha);
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// left or right edge
|
|
//
|
|
|
|
if (bLeftEdge)
|
|
{
|
|
vLeftEdgeDDA(ptData,&tridda);
|
|
}
|
|
else
|
|
{
|
|
vRightEdgeDDA(ptData,&tridda);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vCalulateColorGradient
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 11/20/1996 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vCalulateColorGradient(
|
|
PTRIVERTEX pv0,
|
|
PTRIVERTEX pv1,
|
|
PTRIVERTEX pv2,
|
|
LONG C0,
|
|
LONG C1,
|
|
LONG C2,
|
|
PLONGLONG pArea,
|
|
PLONGLONG pGradXA,
|
|
PLONG pGradX,
|
|
PLONG pGradY
|
|
)
|
|
{
|
|
LONG dCdX = 0;
|
|
LONG dCdY = 0;
|
|
LONGLONG t1,t2,t3,tAll;
|
|
|
|
C0 = C0 << 8;
|
|
C1 = C1 << 8;
|
|
C2 = C2 << 8;
|
|
|
|
//
|
|
// dY
|
|
//
|
|
|
|
t1 = - ((LONGLONG)C0 * (LONGLONG)(pv2->x - pv1->x));
|
|
t2 = - ((LONGLONG)C1 * (LONGLONG)(pv0->x - pv2->x));
|
|
t3 = - ((LONGLONG)C2 * (LONGLONG)(pv1->x - pv0->x));
|
|
tAll = 16 * (t1 + t2 + t3);
|
|
|
|
if (tAll > 0)
|
|
{
|
|
dCdY = (LONG)(tAll / *pArea);
|
|
}
|
|
else if (tAll < 0)
|
|
{
|
|
tAll = -tAll;
|
|
dCdY = (LONG)((tAll - 1) / *pArea);
|
|
dCdY = -(dCdY + 1);
|
|
}
|
|
|
|
*pGradY = dCdY;
|
|
|
|
//
|
|
// Divide by area to get single step x. Keep undivided
|
|
// value around to calc multiple integer step in x
|
|
//
|
|
|
|
|
|
t1 = - ((LONGLONG)C0 * (LONGLONG)(pv2->y - pv1->y));
|
|
t2 = - ((LONGLONG)C1 * (LONGLONG)(pv0->y - pv2->y));
|
|
t3 = - ((LONGLONG)C2 * (LONGLONG)(pv1->y - pv0->y));
|
|
tAll = t1;
|
|
tAll += t2;
|
|
tAll += t3;
|
|
tAll *= 16;
|
|
|
|
*pGradXA = tAll;
|
|
|
|
dCdX = 0;
|
|
|
|
if (tAll > 0)
|
|
{
|
|
dCdX = (LONG)(tAll / *pArea);
|
|
}
|
|
else if (tAll < 0)
|
|
{
|
|
tAll = -tAll;
|
|
dCdX = (LONG)((tAll - 1) / *pArea);
|
|
dCdX = -(dCdX + 1);
|
|
}
|
|
|
|
*pGradX = dCdX;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vCalculateTriangle
|
|
*
|
|
* Calculate color gradients, then scan the three lines that make up the
|
|
* triangle. Fill out a structure that can later be used to fill in the
|
|
* interior of the triangle.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 17-Jul-1996 -by- Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bCalculateTriangle(
|
|
PTRIVERTEX pv0,
|
|
PTRIVERTEX pv1,
|
|
PTRIVERTEX pv2,
|
|
PTRIANGLEDATA ptData
|
|
)
|
|
{
|
|
LONG index;
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vCalculateTriangle:\n");
|
|
DbgPrint("vCalculateTriangle:rcl = [%li,%li] to [%li,%li]\n",
|
|
ptData->rcl.left,
|
|
ptData->rcl.top,
|
|
ptData->rcl.right,
|
|
ptData->rcl.bottom
|
|
);
|
|
DbgPrint("vCalculateTriangle:pv0.x = %li, pv0.y = %li\n",pv0->x,pv0->y);
|
|
DbgPrint("vCalculateTriangle:pv0->Red = 0x%lx, pv0->Green = 0x%lx, pv0->Blue = 0x%lx\n",
|
|
pv0->Red,pv0->Green,pv0->Blue);
|
|
DbgPrint("vCalculateTriangle:pv1.x = %li, pv1.y = %li\n",pv1->x,pv1->y);
|
|
DbgPrint("vCalculateTriangle:pv1->Red = 0x%lx, pv1->Green = 0x%lx, pv1->Blue = 0x%lx\n",
|
|
pv1->Red,pv1->Green,pv1->Blue);
|
|
DbgPrint("vCalculateTriangle:pv2.x = %li, pv2.y = %li\n",pv2->x,pv2->y);
|
|
DbgPrint("vCalculateTriangle:pv2->Red = 0x%lx, pv2->Green = 0x%lx, pv2->Blue = 0x%lx\n",
|
|
pv2->Red,pv2->Green,pv2->Blue);
|
|
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// calc area, color gradients in x,y
|
|
//
|
|
// area = (v2-v0) X (v1 - v2)
|
|
//
|
|
|
|
LONGLONG v12x = pv1->x - pv2->x;
|
|
LONGLONG v12y = pv1->y - pv2->y;
|
|
|
|
LONGLONG v02x = pv0->x - pv2->x;
|
|
LONGLONG v02y = pv0->y - pv2->y;
|
|
|
|
LONGLONG Area = (v12y * v02x) - (v12x * v02y);
|
|
ptData->Area = Area;
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
LONG AreaL = (LONG)Area;
|
|
LONG AreaH = (LONG)(Area/4294967296);
|
|
DbgPrint("vCalculateTriangle:v12x = %lx\n",v12x);
|
|
DbgPrint("vCalculateTriangle:v12y = %lx\n",v12y);
|
|
DbgPrint("vCalculateTriangle:v02x = %lx\n",v02x);
|
|
DbgPrint("vCalculateTriangle:v02y = %lx\n",v02y);
|
|
DbgPrint("vCalculateTriangle:Area = %lx %lx\n",AreaH,AreaL);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// if area is zero then this is a degenerate triangle
|
|
//
|
|
|
|
if (Area == 0)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// calc min and max drawing y
|
|
//
|
|
|
|
ptData->y0 = MAX((pv0->y >> 4),ptData->rcl.top);
|
|
LONG MaxY = (MAX(pv1->y,pv2->y)) >> 4;
|
|
ptData->y1 = MIN(MaxY,ptData->rcl.bottom);
|
|
|
|
//
|
|
// calculate color gradients for each color. There is a little redundant
|
|
// work here with calculation of deltas. Should make this one call or
|
|
// do it in place.
|
|
//
|
|
|
|
vCalulateColorGradient(pv0,pv1,pv2,pv0->Red ,pv1->Red ,pv2->Red ,&Area,&ptData->dRdXA,&ptData->dRdX,&ptData->dRdY);
|
|
vCalulateColorGradient(pv0,pv1,pv2,pv0->Green,pv1->Green,pv2->Green,&Area,&ptData->dGdXA,&ptData->dGdX,&ptData->dGdY);
|
|
vCalulateColorGradient(pv0,pv1,pv2,pv0->Blue ,pv1->Blue ,pv2->Blue ,&Area,&ptData->dBdXA,&ptData->dBdX,&ptData->dBdY);
|
|
vCalulateColorGradient(pv0,pv1,pv2,pv0->Alpha,pv1->Alpha,pv2->Alpha,&Area,&ptData->dAdXA,&ptData->dAdX,&ptData->dAdY);
|
|
|
|
#if DBG
|
|
if (DbgRecord >= 1)
|
|
{
|
|
DbgPrint("vCalculateTriangle:dRdx = 0x%lx,dRdy = 0x%lx\n",ptData->dRdX,ptData->dRdY);
|
|
DbgPrint("vCalculateTriangle:dGdx = 0x%lx,dGdy = 0x%lx\n",ptData->dGdX,ptData->dGdY);
|
|
DbgPrint("vCalculateTriangle:dBdx = 0x%lx,dBdy = 0x%lx\n",ptData->dBdX,ptData->dBdY);
|
|
DbgPrint("vCalculateTriangle:dAdx = 0x%lx,dAdy = 0x%lx\n",ptData->dAdX,ptData->dAdY);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// draw lines into data array
|
|
//
|
|
|
|
vCalculateLine(pv0,pv1,ptData,FALSE);
|
|
vCalculateLine(pv1,pv2,ptData,(pv1->y > pv2->y));
|
|
vCalculateLine(pv2,pv0,ptData,TRUE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* bCalculateTriangle
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 2/12/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
GetNearestEntry(
|
|
PULONG prgbIn,
|
|
ULONG ulNumEntries,
|
|
ALPHAPIX MatchColor
|
|
)
|
|
{
|
|
LONG lError = MAX_INT;
|
|
ULONG ulBest = 0;
|
|
ULONG ulIndex;
|
|
LPRGBQUAD prgb = (LPRGBQUAD)prgbIn;
|
|
|
|
for (ulIndex=0;ulIndex<ulNumEntries;ulIndex++)
|
|
{
|
|
LONG eRed = (LONG)(MatchColor.pix.r - prgb->rgbRed);
|
|
LONG eGreen = (LONG)(MatchColor.pix.g - prgb->rgbGreen);
|
|
LONG eBlue = (LONG)(MatchColor.pix.b - prgb->rgbBlue);
|
|
|
|
eRed = eRed*eRed + eGreen*eGreen + eBlue*eBlue;
|
|
|
|
if (eRed < lError)
|
|
{
|
|
lError = eRed;
|
|
ulBest = ulIndex;
|
|
}
|
|
|
|
prgb++;
|
|
}
|
|
|
|
return((BYTE)ulBest);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* GenColorXform332
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 2/12/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
PBYTE
|
|
pGenColorXform332(
|
|
PULONG ppalIn,
|
|
ULONG ulNumEntries
|
|
)
|
|
{
|
|
ASSERTGDI((ppalIn != NULL),"pGenColorXform332 called with NULL input palette\n");
|
|
ASSERTGDI((ulNumEntries <= 256),"pGenColorXform332 called with invalid ulNumEntries\n");
|
|
|
|
if ((ppalIn == NULL) || (ulNumEntries > 256))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// check for halftone palette
|
|
//
|
|
|
|
if (ulNumEntries == 256)
|
|
{
|
|
if (bIsHalftonePalette(ppalIn))
|
|
{
|
|
return(gHalftoneColorXlate332);
|
|
}
|
|
}
|
|
|
|
//
|
|
// allocate and generate color lookup table
|
|
//
|
|
|
|
PBYTE pxlate = (PBYTE)LOCALALLOC(256);
|
|
|
|
if (pxlate)
|
|
{
|
|
PBYTE pXlateTable = pxlate;
|
|
|
|
//
|
|
// generate color xlate from RGB 332 to palette
|
|
//
|
|
|
|
BYTE Red[8] = {0,37,73,110,146,183,219,255};
|
|
BYTE Green[8] = {0,37,73,110,146,183,219,255};
|
|
BYTE Blue[4] = {0,85,171,255};
|
|
|
|
//
|
|
// ppalOut must be a 256 entry table
|
|
//
|
|
|
|
ULONG ulB,ulG,ulR;
|
|
ALPHAPIX Pixel;
|
|
|
|
for (ulR = 0;ulR<8;ulR++)
|
|
{
|
|
Pixel.pix.r = Red[ulR];
|
|
|
|
for (ulG = 0;ulG<8;ulG++)
|
|
{
|
|
Pixel.pix.g = Green[ulG];
|
|
|
|
for (ulB = 0;ulB<4;ulB++)
|
|
{
|
|
Pixel.pix.b = Blue[ulB];
|
|
*pXlateTable++ = GetNearestEntry(ppalIn,ulNumEntries,Pixel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(pxlate);
|
|
}
|
|
|
|
#endif
|