714 lines
20 KiB
C++
714 lines
20 KiB
C++
#include "plush.h"
|
|
#include "../lice/lice_combine.h"
|
|
|
|
//#define PLUSH_NO_SOLIDFLAT // make non-texturemapped flat shading optimized engine
|
|
//#define PLUSH_NO_SOLIDGOURAUD // disable non-texturemapped gouraud optimized engine
|
|
//#define PLUSH_NO_TEXTURE // disable single-texture optimized engine
|
|
//#define PLUSH_NO_MULTITEXTURE // disable multitexture (this can do any of em)
|
|
#define XPOS_BITS 19 // allows 2^13 max screen width, or 8192px
|
|
|
|
#define SWAP(a,b,t) { t ____tmp=(a); (a)=(b); (b)=____tmp; }
|
|
|
|
#define PUTFACE_SORT() \
|
|
int i0 = 0; int i1 = 1; int i2 = 2; int stat; \
|
|
if (TriFace->Scry[0] > TriFace->Scry[1]) { i0 = 1; i1 = 0; } \
|
|
if (TriFace->Scry[i0] > TriFace->Scry[2]) { SWAP(i0,i2,int); } \
|
|
if (TriFace->Scry[i1] > TriFace->Scry[i2]) { SWAP(i1,i2,int); } \
|
|
int Scrx[3] = {(int)(TriFace->Scrx[0]*(1<<XPOS_BITS)), (int)(TriFace->Scrx[1]*(1<<XPOS_BITS)),(int)(TriFace->Scrx[2]*(1<<XPOS_BITS))}; \
|
|
int Scry[3] = {(int) (TriFace->Scry[0]+0.5), (int) (TriFace->Scry[1]+0.5), (int) (TriFace->Scry[2]+0.5)}; \
|
|
|
|
#define DO_STAT_XDELTAS \
|
|
if (stat & 1) { \
|
|
dX1 = (Scrx[i2]-(X1 = Scrx[i1]))/dY; \
|
|
if (stat & 8) dX2 = (Scrx[i2]-(X2 = Scrx[i0]))/dY; \
|
|
} \
|
|
else if (stat & 2) { \
|
|
dX2 = (Scrx[i2]-(X2 = Scrx[i1]))/dY; \
|
|
if (stat & 4) dX1 = (Scrx[i2]-(X1 = Scrx[i0]))/dY; \
|
|
}
|
|
|
|
|
|
static inline void OverlayBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int usea)
|
|
{
|
|
int da=(256-usea)*128;
|
|
int srcr = r*usea+da, srcg = g*usea+da, srcb = b*usea+da, srca = usea*a + da;
|
|
red = ( red*( (red*(32768-srcr))/256 + srcr ) )/32768;
|
|
green = ( green*( (green*(32768-srcg))/256 + srcg ) )/32768;
|
|
blue = ( blue*( (blue*(32768-srcb))/256 + srcb ) )/32768;
|
|
alpha = ( alpha*( (alpha*(32768-srca))/256 + srca ) )/32768;
|
|
}
|
|
|
|
static inline void MulBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int ta)
|
|
{
|
|
int ta2=(256-ta)*256;
|
|
red = (r*ta*red + red*ta2)/65536;
|
|
green = (g*ta*green + green*ta2)/65536;
|
|
blue = (b*ta*blue + blue*ta2)/65536;
|
|
alpha = (a*ta*alpha + alpha*ta2)/65536;
|
|
}
|
|
|
|
|
|
static inline void AdjustHSV(int &red, int &green, int &blue, int r, int g, int b, int texalpha)
|
|
{
|
|
int h,s,v;
|
|
__LICE_RGB2HSV(red,green,blue,&h,&s,&v);
|
|
h+=(((r+r/2) - 192) * texalpha)/256;
|
|
if (h<0)h+=384;
|
|
else if (h>=384) h-=384;
|
|
s+=((g-128)*texalpha)/256;
|
|
if (s&~0xff)
|
|
{
|
|
if (s<0)s=0;
|
|
else s=255;
|
|
}
|
|
v+=((b-128)*texalpha)/256;
|
|
if (v&~0xff)
|
|
{
|
|
if (v<0)v=0;
|
|
else v=255;
|
|
}
|
|
__LICE_HSV2RGB(h,s,v,&red,&green,&blue);
|
|
}
|
|
|
|
static inline void DodgeBlend(int &red, int &green, int &blue, int &alpha, int r, int g, int b, int a, int ta)
|
|
{
|
|
int src_r = 256-r*ta/256;
|
|
int src_g = 256-g*ta/256;
|
|
int src_b = 256-b*ta/256;
|
|
int src_a = 256-(a*ta)/256;
|
|
|
|
red = src_r > 1 ? 256*red / src_r : 256*red;
|
|
green = src_g > 1 ? 256*green / src_g : 256*green;
|
|
blue = src_b > 1 ? 256*blue / src_b : 256*blue;
|
|
alpha = src_a > 1 ? 256*alpha / src_a : 256*alpha;
|
|
}
|
|
|
|
|
|
static void inline DoTextureCombine(int texcomb, int r, int g, int b, int a, int &red, int &green, int &blue, int &alpha, int texalpha, int texalpha2)
|
|
{
|
|
switch (texcomb)
|
|
{
|
|
case LICE_BLIT_MODE_COPY:
|
|
red = (r*texalpha + red*texalpha2) >> 8;
|
|
green = (g*texalpha + green*texalpha2) >> 8;
|
|
blue = (b*texalpha + blue*texalpha2) >> 8;
|
|
alpha = (a*texalpha + alpha*texalpha2) >> 8;
|
|
break;
|
|
case LICE_BLIT_MODE_ADD:
|
|
red += (r*texalpha) >> 8;
|
|
green += (g*texalpha) >> 8;
|
|
blue += (b*texalpha) >> 8;
|
|
alpha += (a*texalpha) >> 8;
|
|
break;
|
|
case LICE_BLIT_MODE_MUL:
|
|
MulBlend(red,green,blue,alpha,r,g,b,a,texalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_DODGE:
|
|
DodgeBlend(red,green,blue,alpha,r,g,b,a,texalpha);
|
|
|
|
break;
|
|
case LICE_BLIT_MODE_OVERLAY:
|
|
OverlayBlend(red,green,blue,alpha,r,g,b,a, texalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_HSVADJ:
|
|
AdjustHSV(red,green,blue,r,g,b,texalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA:
|
|
{
|
|
int ta=(texalpha*(a+1));
|
|
int ta2=(65536-ta);
|
|
red = (r*ta + red*ta2) >> 16;
|
|
green = (g*ta + green*ta2) >> 16;
|
|
blue = (b*ta + blue*ta2) >> 16;
|
|
alpha = (a*ta + alpha*ta2) >> 16;
|
|
}
|
|
break;
|
|
case LICE_BLIT_MODE_ADD|LICE_BLIT_USE_ALPHA:
|
|
{
|
|
int ta=(texalpha*(a+1));
|
|
red += (r*ta) >> 16;
|
|
green += (g*ta) >> 16;
|
|
blue += (b*ta) >> 16;
|
|
alpha += (a*ta) >> 16;
|
|
}
|
|
break;
|
|
case LICE_BLIT_MODE_DODGE|LICE_BLIT_USE_ALPHA:
|
|
{
|
|
int ta=(texalpha*(a+1))/256;
|
|
DodgeBlend(red,green,blue,alpha,r,g,b,a,ta);
|
|
}
|
|
break;
|
|
case LICE_BLIT_MODE_MUL|LICE_BLIT_USE_ALPHA:
|
|
MulBlend(red,green,blue,alpha,r,g,b,a,(texalpha*(a+1))/256);
|
|
break;
|
|
case LICE_BLIT_MODE_OVERLAY|LICE_BLIT_USE_ALPHA:
|
|
OverlayBlend(red,green,blue,alpha,r,g,b,a, (texalpha*(a+1))/256);
|
|
break;
|
|
case LICE_BLIT_MODE_HSVADJ|LICE_BLIT_USE_ALPHA:
|
|
AdjustHSV(red,green,blue,r,g,b,(texalpha*(a+1))/256);
|
|
break;
|
|
case -2:
|
|
break;
|
|
default:
|
|
red=r; green=g; blue=b; alpha=a;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void inline TextureMakePixelSolidCombine(int &red, int &green, int &blue, int &alpha,
|
|
pl_sInt32 *CL, int solidcomb, int solidalpha,
|
|
int solidalpha2,
|
|
LICE_pixel_chan *gmemptr)
|
|
{
|
|
|
|
switch (solidcomb)
|
|
{
|
|
case LICE_BLIT_MODE_COPY:
|
|
red = ((CL[0]>>8)*solidalpha + gmemptr[LICE_PIXEL_R]*solidalpha2)>>16;
|
|
green = ((CL[1]>>8)*solidalpha + gmemptr[LICE_PIXEL_G]*solidalpha2)>>16;
|
|
blue = ((CL[2]>>8)*solidalpha + gmemptr[LICE_PIXEL_B]*solidalpha2)>>16;
|
|
alpha = solidalpha;
|
|
break;
|
|
case LICE_BLIT_MODE_ADD:
|
|
red = gmemptr[LICE_PIXEL_R] + (((CL[0]>>8)*solidalpha)>>16);
|
|
green = gmemptr[LICE_PIXEL_G] + (((CL[1]>>8)*solidalpha)>>16);
|
|
blue = gmemptr[LICE_PIXEL_B] + (((CL[2]>>8)*solidalpha)>>16);
|
|
alpha = gmemptr[LICE_PIXEL_A] + solidalpha;
|
|
break;
|
|
case LICE_BLIT_MODE_DODGE:
|
|
red=gmemptr[LICE_PIXEL_R];
|
|
green=gmemptr[LICE_PIXEL_G];
|
|
blue=gmemptr[LICE_PIXEL_B];
|
|
alpha=gmemptr[LICE_PIXEL_A];
|
|
DodgeBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha,solidalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_MUL:
|
|
red=gmemptr[LICE_PIXEL_R];
|
|
green=gmemptr[LICE_PIXEL_G];
|
|
blue=gmemptr[LICE_PIXEL_B];
|
|
alpha=gmemptr[LICE_PIXEL_A];
|
|
MulBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha,solidalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_OVERLAY:
|
|
red=gmemptr[LICE_PIXEL_R];
|
|
green=gmemptr[LICE_PIXEL_G];
|
|
blue=gmemptr[LICE_PIXEL_B];
|
|
alpha=gmemptr[LICE_PIXEL_A];
|
|
OverlayBlend(red,green,blue,alpha,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha, solidalpha);
|
|
break;
|
|
case LICE_BLIT_MODE_HSVADJ:
|
|
red=gmemptr[LICE_PIXEL_R];
|
|
green=gmemptr[LICE_PIXEL_G];
|
|
blue=gmemptr[LICE_PIXEL_B];
|
|
alpha=gmemptr[LICE_PIXEL_A];
|
|
AdjustHSV(red,green,blue,CL[0]>>16,CL[1]>>16,CL[2]>>16,solidalpha);
|
|
break;
|
|
case -2:
|
|
red=gmemptr[LICE_PIXEL_R];
|
|
green=gmemptr[LICE_PIXEL_G];
|
|
blue=gmemptr[LICE_PIXEL_B];
|
|
alpha=gmemptr[LICE_PIXEL_A];
|
|
break;
|
|
default:
|
|
red=CL[0]>>16;
|
|
green=CL[1]>>16;
|
|
blue=CL[2]>>16;
|
|
alpha=solidalpha;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void inline TextureMakePixel2(LICE_pixel_chan *gmemptr,
|
|
int solidcomb, int solidalpha, int solidalpha2,
|
|
pl_sInt32 *CL,
|
|
bool bilinear,
|
|
pl_sInt32 iUL, pl_sInt32 iVL,
|
|
pl_sInt32 texwidth, pl_sInt32 texheight,
|
|
LICE_pixel *texture, int tex_rowspan,
|
|
int texcomb,
|
|
int texalpha,
|
|
int texalpha2,
|
|
bool bilinear2,
|
|
pl_sInt32 iUL_2, pl_sInt32 iVL_2,
|
|
pl_sInt32 texwidth_2, pl_sInt32 texheight_2,
|
|
LICE_pixel *texture2, int tex_rowspan_2,
|
|
int tex2comb,
|
|
int tex2alpha,
|
|
int tex2alpha2)
|
|
{
|
|
|
|
int red,green,blue,alpha;
|
|
|
|
TextureMakePixelSolidCombine(red,green,blue,alpha,CL,solidcomb,solidalpha,solidalpha2,gmemptr);
|
|
|
|
int r,g,b,a;
|
|
|
|
#if defined(PLUSH_NO_TEXTURE)
|
|
if (texture)
|
|
#endif
|
|
{
|
|
const int xpos=(iUL>>14)&~3;
|
|
const int ypos=iVL>>16;
|
|
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture) + xpos+ypos*tex_rowspan;
|
|
|
|
if (bilinear)
|
|
{
|
|
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
|
|
ypos < texheight - 1 ? rd+tex_rowspan : ((LICE_pixel_chan *)texture)+xpos,
|
|
xpos < texwidth - 4 ? 4 : 4-texwidth,
|
|
iUL&65535,iVL&65535);
|
|
}
|
|
else
|
|
{
|
|
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
|
|
}
|
|
|
|
DoTextureCombine(texcomb, r,g,b,a, red,green,blue,alpha,texalpha,texalpha2);
|
|
}
|
|
|
|
#ifdef PLUSH_NO_TEXTURE
|
|
if (texture2)
|
|
#endif
|
|
{
|
|
const int xpos=(iUL_2>>14)&~3;
|
|
const int ypos=iVL_2>>16;
|
|
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture2) + xpos+ypos*tex_rowspan_2;
|
|
|
|
if (bilinear2)
|
|
{
|
|
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
|
|
ypos < texheight_2 - 1 ? rd+tex_rowspan_2 : ((LICE_pixel_chan *)texture2)+xpos,
|
|
xpos < texwidth_2 - 4 ? 4 : 4-texwidth_2,
|
|
iUL_2&65535,iVL_2&65535);
|
|
}
|
|
else
|
|
{
|
|
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
|
|
}
|
|
|
|
DoTextureCombine(tex2comb, r,g,b,a, red,green,blue,alpha,tex2alpha,tex2alpha2);
|
|
}
|
|
|
|
_LICE_MakePixelClamp(gmemptr, red,green,blue,alpha);
|
|
}
|
|
|
|
static void inline TextureMakePixel(LICE_pixel_chan *gmemptr,
|
|
int solidcomb, int solidalpha, int solidalpha2,
|
|
pl_sInt32 *CL,
|
|
bool bilinear,
|
|
pl_sInt32 iUL, pl_sInt32 iVL,
|
|
pl_sInt32 texwidth, pl_sInt32 texheight,
|
|
LICE_pixel *texture, int tex_rowspan,
|
|
int texcomb,
|
|
int texalpha,
|
|
int texalpha2)
|
|
{
|
|
|
|
int red,green,blue,alpha;
|
|
|
|
if (
|
|
#ifdef PLUSH_NO_SOLIDGOURAUD
|
|
!texture||
|
|
#endif
|
|
texcomb!=-1)
|
|
TextureMakePixelSolidCombine(red,green,blue,alpha,CL,solidcomb,solidalpha,solidalpha2,gmemptr);
|
|
|
|
|
|
|
|
#ifdef PLUSH_NO_SOLIDGOURAUD
|
|
if (texture)
|
|
#endif
|
|
{
|
|
int r,g,b,a;
|
|
const int xpos=(iUL>>14)&~3;
|
|
const int ypos=iVL>>16;
|
|
const LICE_pixel_chan *rd = ((LICE_pixel_chan*)texture) + xpos+ypos*tex_rowspan;
|
|
|
|
if (bilinear)
|
|
{
|
|
|
|
__LICE_BilinearFilterI_2(&r,&g,&b,&a,rd,
|
|
ypos < texheight - 1 ? rd+tex_rowspan : ((LICE_pixel_chan *)texture)+xpos,
|
|
xpos < texwidth - 4 ? 4 : 4-texwidth,
|
|
iUL&65535,iVL&65535);
|
|
}
|
|
else
|
|
{
|
|
r=rd[LICE_PIXEL_R]; g=rd[LICE_PIXEL_G]; b=rd[LICE_PIXEL_B]; a=rd[LICE_PIXEL_A];
|
|
}
|
|
|
|
DoTextureCombine(texcomb, r,g,b,a, red,green,blue,alpha,texalpha,texalpha2);
|
|
}
|
|
|
|
_LICE_MakePixelClamp(gmemptr, red,green,blue,alpha);
|
|
}
|
|
|
|
|
|
|
|
#ifndef PLUSH_NO_TEXTURE
|
|
#include "pl_pf_tex.h"
|
|
#endif
|
|
|
|
#ifndef PLUSH_NO_MULTITEXTURE
|
|
#define PL_PF_MULTITEX
|
|
#include "pl_pf_tex.h"
|
|
#endif
|
|
|
|
|
|
|
|
|
|
template<class Comb> class PLSolidPutFace
|
|
{
|
|
public:
|
|
#ifndef PLUSH_NO_SOLIDGOURAUD
|
|
static void SolidGouraud(LICE_pixel *gmem, int swidth, pl_Face *TriFace, int alpha, pl_ZBuffer *zbuf, int zfb_width, bool zb_update)
|
|
{
|
|
pl_Float dZL=0, dZ1=0, dZ2=0;
|
|
pl_sInt32 dX1=0, dX2=0, C1[3], C2[3], dC1[3]={0}, dC2[3]={0}, dCL[3]={0}, C3[3];
|
|
|
|
PUTFACE_SORT();
|
|
|
|
|
|
int a;
|
|
for(a=0;a<3;a++)
|
|
{
|
|
C1[a] = (pl_sInt32) (TriFace->Shades[i0][a]*(1<<24));
|
|
C2[a] = (pl_sInt32) (TriFace->Shades[i1][a]*(1<<24));
|
|
C3[a] = (pl_sInt32) (TriFace->Shades[i2][a]*(1<<24));
|
|
}
|
|
pl_sInt32 X2,X1;
|
|
X2 = X1 = Scrx[i0];
|
|
pl_Float Z1 = TriFace->Scrz[i0];
|
|
pl_Float Z2 = TriFace->Scrz[i1];
|
|
pl_Float Z3 = TriFace->Scrz[i2];
|
|
|
|
pl_sInt32 Y0 = Scry[i0];
|
|
pl_sInt32 Y1 = Scry[i1];
|
|
pl_sInt32 Y2 = Scry[i2];
|
|
|
|
{
|
|
pl_sInt32 dY = Y2 - Y0;
|
|
if (dY) {
|
|
dX2 = (Scrx[i2] - X1) / dY;
|
|
for(a=0;a<3;a++) dC2[a] = (C3[a] - C1[a]) / dY;
|
|
dZ2 = (Z3 - Z1) / dY;
|
|
}
|
|
dY = Y1 - Y0;
|
|
if (dY) {
|
|
dX1 = (Scrx[i1] - X1) / dY;
|
|
for(a=0;a<3;a++)
|
|
dC1[a] = (C2[a] - C1[a]) / dY;
|
|
dZ1 = (Z2 - Z1) / dY;
|
|
if (dX2 < dX1) {
|
|
SWAP(dX2,dX1,pl_sInt32);
|
|
for(a=0;a<3;a++) SWAP(dC1[a],dC2[a],pl_sInt32);
|
|
SWAP(dZ1,dZ2,pl_Float);
|
|
stat = 2;
|
|
} else stat = 1;
|
|
Z2 = Z1;
|
|
C2[0] = C1[0];
|
|
C2[1] = C1[1];
|
|
C2[2] = C1[2];
|
|
} else {
|
|
if (Scrx[i1] > X1) {
|
|
X2 = Scrx[i1];
|
|
stat = 2|4;
|
|
} else {
|
|
for(a=0;a<3;a++) SWAP(C1[a],C2[a],pl_sInt32);
|
|
SWAP(Z1,Z2,pl_Float);
|
|
X1 = Scrx[i1];
|
|
stat = 1|8;
|
|
}
|
|
}
|
|
|
|
pl_sInt32 tmp = (dX1-dX2)*dY;
|
|
if (tmp) {
|
|
double v=(1<<XPOS_BITS)/(double)tmp;
|
|
for(a=0;a<3;a++)
|
|
dCL[a] = (pl_sInt32) (((dC1[a]-dC2[a])*dY)*v);
|
|
dZL = ((dZ1-dZ2)*dY)*v;
|
|
} else {
|
|
tmp = X2-X1;
|
|
if (tmp) {
|
|
double v=(1<<XPOS_BITS)/(double)tmp;
|
|
for(a=0;a<3;a++)
|
|
dCL[a] = (pl_sInt32) ((C2[a]-C1[a])*v);
|
|
dZL = (Z2-Z1)*v;
|
|
}
|
|
}
|
|
}
|
|
|
|
gmem += (Y0 * swidth);
|
|
zbuf += (Y0 * zfb_width);
|
|
|
|
while (Y0 < Y2) {
|
|
if (Y0 == Y1) {
|
|
pl_sInt32 dY = Y2 - Scry[i1];
|
|
if (dY) {
|
|
double v=1.0/dY;
|
|
dZ1 = (Z3-Z1)*v;
|
|
dC1[0] = (pl_sInt32) ((C3[0]-C1[0])*v);
|
|
dC1[1] = (pl_sInt32) ((C3[1]-C1[1])*v);
|
|
dC1[2] = (pl_sInt32) ((C3[2]-C1[2])*v);
|
|
|
|
DO_STAT_XDELTAS
|
|
|
|
}
|
|
}
|
|
pl_sInt32 XL1 = (X1+(1<<(XPOS_BITS-1)))>>XPOS_BITS;
|
|
pl_sInt32 XL2 = ((X2+(1<<(XPOS_BITS-1)))>>XPOS_BITS) - XL1;
|
|
if (XL2 > 0) {
|
|
gmem += XL1;
|
|
XL1 += XL2;
|
|
pl_sInt32 CL[3] = {C1[0],C1[1],C1[2]};
|
|
if (zbuf)
|
|
{
|
|
pl_Float ZL = Z1;
|
|
zbuf += XL1-XL2;
|
|
do {
|
|
if (*zbuf < ZL) {
|
|
if (zb_update) *zbuf = (pl_ZBuffer) ZL;
|
|
|
|
Comb::doPix((LICE_pixel_chan *)gmem,CL[0]>>16,CL[1]>>16,CL[2]>>16,255,alpha);
|
|
}
|
|
gmem++;
|
|
zbuf++;
|
|
ZL += dZL;
|
|
CL[0] += dCL[0];
|
|
CL[1] += dCL[1];
|
|
CL[2] += dCL[2];
|
|
} while (--XL2);
|
|
zbuf -= XL1;
|
|
}
|
|
else do {
|
|
Comb::doPix((LICE_pixel_chan *)gmem,CL[0]>>16,CL[1]>>16,CL[2]>>16,255,alpha);
|
|
gmem++;
|
|
CL[0] += dCL[0];
|
|
CL[1] += dCL[1];
|
|
CL[2] += dCL[2];
|
|
} while (--XL2);
|
|
gmem -= XL1;
|
|
}
|
|
gmem += swidth;
|
|
zbuf += zfb_width;
|
|
X1 += dX1;
|
|
X2 += dX2;
|
|
C1[0] += dC1[0];
|
|
C1[1] += dC1[1];
|
|
C1[2] += dC1[2];
|
|
Z1 += dZ1;
|
|
Y0++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef PLUSH_NO_SOLIDFLAT
|
|
static void Solid(LICE_pixel *gmem, int swidth, pl_Face *TriFace, int alpha, pl_ZBuffer *zbuf, int zfb_width, bool zb_update)
|
|
{
|
|
pl_sInt32 dX1=0, dX2=0;
|
|
pl_Float dZL=0, dZ1=0, dZ2=0;
|
|
|
|
PUTFACE_SORT();
|
|
|
|
int col0 = (int) (TriFace->Shades[0][0]*255.0);
|
|
int col1 = (int) (TriFace->Shades[0][1]*255.0);
|
|
int col2 = (int) (TriFace->Shades[0][2]*255.0);
|
|
|
|
pl_sInt32 X1,X2;
|
|
X2 = X1 = Scrx[i0];
|
|
pl_sInt32 Y0 = Scry[i0];
|
|
pl_sInt32 Y1 = Scry[i1];
|
|
pl_sInt32 Y2 = Scry[i2];
|
|
|
|
pl_Float Z1 = TriFace->Scrz[i0];
|
|
pl_Float Z2 = TriFace->Scrz[i1];
|
|
pl_Float Z3 = TriFace->Scrz[i2];
|
|
|
|
{
|
|
pl_sInt32 dY = Y2-Y0;
|
|
if (dY) {
|
|
dX2 = (Scrx[i2] - X1) / dY;
|
|
dZ2 = (Z3 - Z1) / dY;
|
|
}
|
|
dY = Y1-Y0;
|
|
if (dY) {
|
|
dX1 = (Scrx[i1] - X1) / dY;
|
|
dZ1 = (Z2 - Z1) / dY;
|
|
if (dX2 < dX1) {
|
|
SWAP(dX1,dX2,pl_sInt32);
|
|
SWAP(dZ1,dZ2,pl_Float);
|
|
stat = 2;
|
|
} else stat = 1;
|
|
Z2 = Z1;
|
|
} else {
|
|
if (Scrx[i1] > X1) {
|
|
X2 = Scrx[i1];
|
|
stat = 2|4;
|
|
} else {
|
|
X1 = Scrx[i1];
|
|
SWAP(Z1,Z2,pl_Float);
|
|
stat = 1|8;
|
|
}
|
|
}
|
|
|
|
if (zbuf)
|
|
{
|
|
pl_sInt32 tmp=(dX1-dX2)*dY;
|
|
if (tmp) dZL = ((dZ1-dZ2)*dY)*(double)(1<<XPOS_BITS)/(double)tmp;
|
|
else {
|
|
tmp = X2-X1;
|
|
if (tmp) dZL = (Z2-Z1)*(double)(1<<XPOS_BITS)/tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
gmem += (Y0 * swidth);
|
|
zbuf += (Y0 * zfb_width);
|
|
|
|
while (Y0 < Y2) {
|
|
if (Y0 == Y1) {
|
|
pl_sInt32 dY = Y2 - Scry[i1];
|
|
if (dY) {
|
|
DO_STAT_XDELTAS
|
|
dZ1 = (Z3-Z1)/dY;
|
|
}
|
|
}
|
|
pl_sInt32 XL1 = (X1+(1<<(XPOS_BITS-1)))>>XPOS_BITS;
|
|
pl_sInt32 XL2 = ((X2+(1<<(XPOS_BITS-1)))>>XPOS_BITS) - XL1;
|
|
if (XL2 > 0) {
|
|
gmem += XL1;
|
|
XL1 += XL2;
|
|
if (zbuf)
|
|
{
|
|
pl_Float ZL = Z1;
|
|
zbuf += XL1-XL2;
|
|
do {
|
|
if (*zbuf < ZL) {
|
|
if (zb_update) *zbuf = (pl_ZBuffer) ZL;
|
|
Comb::doPix((LICE_pixel_chan *)gmem,col0,col1,col2,255,alpha);
|
|
}
|
|
gmem++;
|
|
zbuf++;
|
|
ZL += dZL;
|
|
} while (--XL2);
|
|
zbuf -= XL1;
|
|
}
|
|
else
|
|
{
|
|
do {
|
|
Comb::doPix((LICE_pixel_chan *)gmem,col0,col1,col2,255,alpha);
|
|
gmem++;
|
|
} while (--XL2);
|
|
}
|
|
gmem -= XL1;
|
|
|
|
}
|
|
gmem += swidth;
|
|
zbuf += zfb_width;
|
|
Z1 += dZ1;
|
|
X1 += dX1;
|
|
X2 += dX2;
|
|
Y0++;
|
|
}
|
|
}
|
|
#endif
|
|
};
|
|
|
|
void pl_Cam::PutFace(pl_Face *TriFace)
|
|
{
|
|
LICE_pixel *gmem = m_fBuffer.m_buf;
|
|
if (WDL_NOT_NORMALLY(!gmem)) return;
|
|
|
|
int zfb_width = 0;
|
|
int zBufferable = TriFace->Material->zBufferable;
|
|
pl_ZBuffer *zb = NULL;
|
|
if (zBufferable &&
|
|
zBuffer.GetSize() &&
|
|
WDL_NORMALLY(zBuffer.GetSize() >= m_fBuffer.m_w*m_fBuffer.m_h)
|
|
)
|
|
{
|
|
zfb_width = m_fBuffer.m_w;
|
|
zb = zBuffer.Get();
|
|
}
|
|
|
|
int swidth = m_fBuffer.m_span;
|
|
if (m_fBuffer.m_flipped)
|
|
{
|
|
gmem += swidth*(m_fBuffer.m_h-1);
|
|
swidth=-swidth;
|
|
}
|
|
|
|
pl_Mat *mat=TriFace->Material;
|
|
|
|
#ifndef PLUSH_NO_MULTITEXTURE
|
|
|
|
#ifndef PLUSH_NO_TEXTURE
|
|
if (mat->Texture&&mat->Texture2)
|
|
#else
|
|
#ifndef PLUSH_NO_SOLIDGOURAUD
|
|
if (mat->Texture||mat->Texture2)
|
|
#endif
|
|
#endif
|
|
{
|
|
pl_Float texsc[4];
|
|
memcpy(texsc,mat->TexScaling,sizeof(mat->TexScaling));
|
|
memcpy(texsc+2,mat->Tex2Scaling,sizeof(mat->Tex2Scaling));
|
|
int tidx = mat->TexMapIdx;
|
|
if (tidx<0 || tidx>=PLUSH_MAX_MAPCOORDS)tidx=PLUSH_MAX_MAPCOORDS-1;
|
|
int tidx2 = mat->Tex2MapIdx;
|
|
if (tidx2<0 || tidx2>=PLUSH_MAX_MAPCOORDS)tidx2=PLUSH_MAX_MAPCOORDS-1;
|
|
|
|
PLMTexTri(gmem,swidth,TriFace,zb,zfb_width,zBufferable!=2,(int) (mat->SolidOpacity*256.0),mat->SolidCombineMode,
|
|
mat->Texture,texsc,(int) (mat->TexOpacity*256.0),mat->TexCombineMode,tidx,
|
|
mat->Texture2,(int) (mat->Tex2Opacity*256.0),mat->Tex2CombineMode,tidx2
|
|
);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef PLUSH_NO_TEXTURE
|
|
#ifndef PLUSH_NO_SOLIDGOURAUD
|
|
if (mat->Texture||mat->Texture2)
|
|
#endif
|
|
{
|
|
LICE_IBitmap *tex=mat->Texture ? mat->Texture : mat->Texture2;
|
|
int talpha = (int) (mat->Texture ? mat->TexOpacity*256.0 : mat->Tex2Opacity*256.0);
|
|
int tcomb = (int) (mat->Texture ? mat->TexCombineMode : mat->Tex2CombineMode);
|
|
int tidx = (mat->Texture ? mat->TexMapIdx: mat->Tex2MapIdx);
|
|
if (tidx<0 || tidx>=PLUSH_MAX_MAPCOORDS)tidx=PLUSH_MAX_MAPCOORDS-1;
|
|
pl_Float texsc[2];
|
|
memcpy(texsc,mat->Texture ? mat->TexScaling : mat->Tex2Scaling,sizeof(texsc));
|
|
PLTexTri(gmem,swidth,TriFace,zb,zfb_width,zBufferable!=2,(int) (mat->SolidOpacity*256.0),mat->SolidCombineMode,tex,texsc,talpha,tcomb,tidx);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
int alpha=(int) (mat->SolidOpacity*256.0);
|
|
if (!alpha) return;
|
|
|
|
#ifndef PLUSH_NO_SOLIDGOURAUD
|
|
#ifndef PLUSH_NO_SOLIDFLAT
|
|
if (mat->Smoothing)
|
|
#endif
|
|
{
|
|
#define __LICE__ACTION(comb) PLSolidPutFace<comb>::SolidGouraud(gmem,swidth,TriFace,alpha,zb,zfb_width, zBufferable!=2);
|
|
__LICE_ACTION_CONSTANTALPHA(mat->SolidCombineMode,alpha,true);
|
|
#undef __LICE__ACTION
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifndef PLUSH_NO_SOLIDFLAT
|
|
|
|
#define __LICE__ACTION(comb) PLSolidPutFace<comb>::Solid(gmem,swidth,TriFace,alpha,zb,zfb_width, zBufferable!=2);
|
|
__LICE_ACTION_CONSTANTALPHA(mat->SolidCombineMode,alpha,true);
|
|
#undef __LICE__ACTION
|
|
|
|
#endif // PLUSH_NO_SOLIDFLAT
|
|
}
|
|
|
|
|