📄 render.cpp
字号:
if(c > f)
{
goto EXIT_LOOP3;
}
*td =color;
}
goto LOOP3;
EXIT_LOOP3:
;
}
return;
}
else
{
if(c <= f)
{
*td =color;
LOOP4:
td +=Cam->Width;
c++;
if(g >= 0)
{
r--;
g +=inc2;
td--;
if(c > f)
{
goto EXIT_LOOP4;
}
*td =color;
}
else
{
g +=inc1;
if(c > f)
{
goto EXIT_LOOP4;
}
*td =color;
}
goto LOOP4;
EXIT_LOOP4:
;
}
}
}
}
void Render_BlitViewDib(ViewVars *v, HDC ViewDC)
{
if(StretchDIBits(ViewDC, 0, 0, v->Width, v->Height,
0, 0, v->Width, v->Height, v->pBits, (BITMAPINFO *)&v->ViewBMI,
DIB_RGB_COLORS, SRCCOPY)==GDI_ERROR)
{
// ConPrintf("Could not blit to screen!"); // old gedit
CGlobals::GetActiveDocument()->mpMainFrame->ConPrintf("Could not blit to screen!"); // new g3dc
assert(0);
}
}
static void ClearZBuffer(ViewVars *Cam)
{
memset(Cam->pZBuffer, 0, (sizeof(uint32) * (Cam->Width*Cam->Height)));
}
void Render_RenderSpanFaceCB(Face *f, const Face *OGFace, int Key, geFloat pdist, int RFlags, void *pVoid)
{
int i;
RenderFace TempFace, Clipped, Unclipped;
const geVec3d *pnts;
ViewVars *Cam =(ViewVars *)pVoid;
if(Face_IsVisible(f))
{
if(pdist > ON_EPSILON)
{
if(ClipToFrustum(f, &TempFace, Cam))
{
pnts =Face_GetPoints(f);
for(i=0;i < TempFace.NumPoints;i++)
{
Clipped.Points[i] =Render_XFormVert(Cam, &TempFace.Points[i]);
}
for(i=0;i < Face_GetNumPoints(f);i++)
{
Unclipped.Points[i] =Render_XFormVert(Cam, &pnts[i]);
}
Clipped.NumPoints =TempFace.NumPoints;
Unclipped.NumPoints =Face_GetNumPoints(f); //could use i here but unclear/risky
AddNodeEdges(f, OGFace, &Clipped, &Unclipped, Key, Cam, RFlags);
}
}
else if(Face_IsSheet(f))
{
if(ClipToFrustum(f, &TempFace, Cam))
{
pnts =Face_GetPoints(f);
for(i=0;i < TempFace.NumPoints;i++)
{
Clipped.Points[TempFace.NumPoints-(i+1)] =Render_XFormVert(Cam, &TempFace.Points[i]);
}
Unclipped.NumPoints =Face_GetNumPoints(f); //could use i here but unclear/risky
Clipped.NumPoints =TempFace.NumPoints;
for(i=0;i < Face_GetNumPoints(f);i++)
{
Unclipped.Points[Unclipped.NumPoints-(i+1)] =Render_XFormVert(Cam, &pnts[i]);
}
AddNodeEdges(f, OGFace, &Clipped, &Unclipped, Key, Cam, RFlags | FLIPPED);
}
}
}
}
void Render_ClearViewDib (ViewVars *Cam)
{
memset(Cam->pBits, 0, Cam->Width * Cam->Height *2);
ClearZBuffer(Cam); //TODO: vtune this, might march
}
void Render_RenderTree(ViewVars *Cam, Node *n, HDC ViewDC, int RFlags)
{
ClearEdgeLists(Cam);
pAvailSurf =surfz;
pAvailEdge =edgez;
if(RFlags & ZFILL)
{
Render_ClearViewDib (Cam);
}
Node_EnumTreeFaces(n, &Cam->CamPos, RFlags, (void *)Cam, Render_RenderSpanFaceCB);
if(RFlags & ZFILL)
{
FillBackSpans(Cam);
}
ScanEdges(Cam);
DrawSpans(Cam, ViewDC);
}
static void AddNodeEdges(Face *NodeFace, //node face
const Face *OGFace,//original brush face
RenderFace *sf, //screenspace clipped
RenderFace *sfnc, //screenspace unclipped
uint32 Key, //bspsortkey
ViewVars *Cam, //viewvars
int RFlags) //render flags
{
Plane SPlane;
geVec3d tview, tworld;
int i, nextvert, topy, bottomy, height, temp, DibId = 0;
int NFaceNumPoints = 0;
geFloat deltax, deltay, slope, psfov, dinv, zinv;
geFloat aUOverZ, aVOverZ, dzinv, u, v;
SpanSurface *spsf;
Edge *pedge;
geBoolean GradNeeded, Sheet;
TexInfo_Vectors const *TVecs = NULL;
const geVec3d *NFacePnts = NULL;
const Plane *NPlane = NULL;
spsf =&SpanFaces[Cam->FacesDone];
Sheet =Face_IsSheet(NodeFace);
if(OGFace)
{
DibId =Face_GetTextureDibId(OGFace);
TVecs =Face_GetTextureVecs(OGFace);
GradNeeded =(DibId!=0xffff)&&(!Face_IsSky(OGFace));
NPlane =Face_GetPlane(OGFace);
NFacePnts =Face_GetPoints(NodeFace);
NFaceNumPoints =Face_GetNumPoints(NodeFace);
}
else
{
GradNeeded =FALSE;
}
//TODO: clamp sf to window limits
for(i=0;i < sf->NumPoints;i++)
{
assert(sf->Points);
nextvert=(i+1)%sf->NumPoints;
topy =(int)ceil(sf->Points[i].Y);
bottomy =(int)ceil(sf->Points[nextvert].Y);
height =bottomy-topy;
if(height==0)
continue; //doesn't cross any scan lines
if(height < 0) //leading edge
{
temp =topy;
topy =bottomy;
bottomy =temp;
pAvailEdge->leading=1;
deltax = sf->Points[i].X -sf->Points[nextvert].X;
deltay = sf->Points[i].Y -sf->Points[nextvert].Y;
slope = deltax/deltay;
pAvailEdge->xstep=(int)(slope * (geFloat)0x10000);
pAvailEdge->x=(int)((sf->Points[nextvert].X +
((geFloat)topy - sf->Points[nextvert].Y) * slope) * (geFloat)0x10000);
}
else
{
pAvailEdge->leading=0;
deltax = sf->Points[nextvert].X -sf->Points[i].X;
deltay = sf->Points[nextvert].Y -sf->Points[i].Y;
slope = deltax/deltay;
pAvailEdge->xstep = (int)(slope * (geFloat)0x10000);
pAvailEdge->x=(int)((sf->Points[i].X +((geFloat)topy - sf->Points[i].Y)
* slope) *(geFloat)0x10000);
}
pedge =&Cam->NewEdges[topy];
while(pedge->pnext->x < pAvailEdge->x)
pedge =pedge->pnext;
pAvailEdge->pnext =pedge->pnext;
pedge->pnext =pAvailEdge;
pAvailEdge->pnextremove =Cam->RemoveEdges[bottomy - 1];
Cam->RemoveEdges[bottomy - 1] =pAvailEdge;
pAvailEdge->psurf =pAvailSurf;
if(pAvailEdge < &edgez[MAX_EDGES])
pAvailEdge++;
}
spsf->sizes.ScreenWidth =Cam->Width;
spsf->sizes.ScreenHeight=Cam->Height;
if(GradNeeded) //texture gradient needed
{
spsf->sizes.TexWidth =Cam->WadSizes[DibId].TexWidth;
spsf->sizes.TexHeight =Cam->WadSizes[DibId].TexHeight;
spsf->sizes.TexData =Cam->WadSizes[DibId].TexData;
//rotate the faces plane into the view
SPlane.Normal.X =geVec3d_DotProduct(&NPlane->Normal, &Cam->Vright);
SPlane.Normal.Y =geVec3d_DotProduct(&NPlane->Normal, &Cam->Vup);
SPlane.Normal.Z =geVec3d_DotProduct(&NPlane->Normal, &Cam->Vpn);
SPlane.Dist =NPlane->Dist - geVec3d_DotProduct(&Cam->CamPos, &NPlane->Normal);
//calc 1/z gradients
psfov =Cam->MaxScreenScaleInv*(Cam->FieldOfView/2.0f);
dinv =1.0f/SPlane.Dist;
spsf->Grads.dOneOverZdX =-SPlane.Normal.X*dinv*psfov;
spsf->zinvstepy =-SPlane.Normal.Y*dinv*psfov;
// spsf->zinv00 =SPlane.Normal.Z*dinv-Cam->XCenter*spsf->Grads.dOneOverZdX
// -Cam->YCenter*spsf->zinvstepy;
spsf->zinv00 =SPlane.Normal.Z*dinv
-Cam->XCenter*spsf->Grads.dOneOverZdX
-Cam->YCenter*spsf->zinvstepy;
//use the worldspace face to get a starting U and V
//if faces are flipped, clipped index zero is world nv-1
if(RFlags & FLIPPED)
{
u =geVec3d_DotProduct(&NFacePnts[NFaceNumPoints-1], &TVecs->uVec) + TVecs->uOffset;
v =geVec3d_DotProduct(&NFacePnts[NFaceNumPoints-1], &TVecs->vVec) + TVecs->vOffset;
}
else
{
u =geVec3d_DotProduct(&NFacePnts[0], &TVecs->uVec) + TVecs->uOffset;
v =geVec3d_DotProduct(&NFacePnts[0], &TVecs->vVec) + TVecs->vOffset;
}
//unclipped screen face will have the same zero index
zinv =1.0f / sfnc->Points[0].Z;
aUOverZ =u *zinv;
aVOverZ =v *zinv;
//step 256 pixels in screen x to get u v z deltas
dzinv=(zinv+spsf->Grads.dOneOverZdX*(256.0f));
//step point zero 256 in screen x and unproject back to view
// tview.X =(sfnc->Points[0].X +256.0f -Cam->XCenter)/(Cam->MaxScale*dzinv);
tview.X =(sfnc->Points[0].X +256.0f -Cam->XCenter)/(Cam->MaxScale*-dzinv);
tview.Y =(sfnc->Points[0].Y -Cam->YCenter)/(Cam->MaxScale*-dzinv);
tview.Z =1.0f / dzinv;
//rotate the point back to worldspace
Render_BackRotateVector(Cam, &tview, &tworld);
geVec3d_Add(&tworld, &Cam->CamPos, &tworld);
//grab x deltas from the new point for u and v
u =geVec3d_DotProduct(&tworld, &TVecs->uVec) + TVecs->uOffset;
v =geVec3d_DotProduct(&tworld, &TVecs->vVec) + TVecs->vOffset;
spsf->Grads.dUOverZdX=(dzinv*u -aUOverZ)/256.0f;
spsf->Grads.dVOverZdX=(dzinv*v -aVOverZ)/256.0f;
//step 256 pixels in screen y to get u v z deltas
dzinv=(zinv+spsf->zinvstepy*(256.0f));
//step point zero 256 in screen y and unproject back to view
// tview.X =(sfnc->Points[0].X -Cam->XCenter)/(Cam->MaxScale*dzinv);
tview.X =(sfnc->Points[0].X -Cam->XCenter)/(Cam->MaxScale*-dzinv);
tview.Y =(sfnc->Points[0].Y +256.0f -Cam->YCenter)/(Cam->MaxScale*-dzinv);
tview.Z =1.0f / dzinv;
//rotate the point back to worldspace
Render_BackRotateVector(Cam, &tview, &tworld);
geVec3d_Add(&tworld, &Cam->CamPos, &tworld);
//grab y deltas from the new point for u and v
u =geVec3d_DotProduct(&tworld, &TVecs->uVec) + TVecs->uOffset;
v =geVec3d_DotProduct(&tworld, &TVecs->vVec) + TVecs->vOffset;
spsf->zinvustepy=(dzinv*u -aUOverZ)/256.0f;
spsf->zinvvstepy=(dzinv*v -aVOverZ)/256.0f;
//calculate u/z and v/z at screen 0,0
spsf->zinvu00=aUOverZ -
sfnc->Points[0].X * spsf->Grads.dUOverZdX -
sfnc->Points[0].Y * spsf->zinvustepy;
spsf->zinvv00=aVOverZ -
sfnc->Points[0].X * spsf->Grads.dVOverZdX -
sfnc->Points[0].Y * spsf->zinvvstepy;
//these can be added to a span subdiv with no mul
spsf->Grads.dOneOverZdX16 = spsf->Grads.dOneOverZdX * 16.0f;
spsf->Grads.dUOverZdX16 = spsf->Grads.dUOverZdX * 16.0f;
spsf->Grads.dVOverZdX16 = spsf->Grads.dVOverZdX * 16.0f;
}
else //non textured
{
spsf->sizes.TexWidth =0;
spsf->sizes.TexHeight =0;
spsf->sizes.TexData =NULL;
}
spsf->head =NULL;
spsf->cur =NULL;
pAvailSurf->state =0;
pAvailSurf->sfIdx =Cam->FacesDone++;
pAvailSurf->Key =Key;
pAvailSurf->RFlag =RFlags;
if(OGFace)
{
pAvailSurf->color =(Face_IsSky(OGFace))? 0x2bf: (0x00b0b0b0-Key);
}
else
{
pAvailSurf->color =(0x00b0b0b0-Key);
}
//make sure the surface array isn't full
if(pAvailSurf < &surfz[MAX_SURFS])
pAvailSurf++;
}
//this turns the edge list into spans sorted by texture
//the inner calculations of left and right u and v over z
//could really use some assembly. I'll save that for later
//pollard has MUCH better span code, I need to implement it here
static void ScanEdges(ViewVars *Cam)
{
int x, y, zinv, zinv2;
Edge *pedge, *pedge2, *ptemp;
Span *pspan;
Surf *psurf, *psurf2;
SpanSurface *sstemp;
pspan = spanz;
edgeHead.pnext =&edgeTail;
edgeHead.pprev =NULL;
edgeHead.x =-0xFFFF; // left edge of screen
edgeHead.leading=1;
edgeHead.psurf =&SurfStack;
edgeTail.pnext =NULL; // mark edge of list
edgeTail.pprev =&edgeHead;
edgeTail.x =Cam->Width << 16; // right edge of screen
edgeTail.leading=0;
edgeTail.psurf =&SurfStack;
SurfStack.pnext=SurfStack.pprev=&SurfStack;
SurfStack.color=0;
SurfStack.Key=-999999;
for(y=0;y < Cam->Height;y++)
{
pedge =Cam->NewEdges[y].pnext;
pedge2 =&edgeHead;
while(pedge!=&MaxEdge)
{
while(pedge->x > pedge2->pnext->x)
{
pedge2=pedge2->pnext;
}
ptemp = pedge->pnext;
pedge->pnext = pedge2->pnext;
pedge->pprev = pedge2;
pedge2->pnext->pprev = pedge;
pedge2->pnext = pedge;
pedge2 = pedge;
pedge = ptemp;
}
SurfStack.state = 1;
SurfStack.visxstart = 0;
for(pedge=edgeHead.pnext;pedge;pedge=pedge->pnext)
{
psurf = pedge->psurf;
if(pedge->leading)
{
if(++psurf->state==1)
{
zinv =psurf->Key;
psurf2 =SurfStack.pnext;
zinv2 =psurf2->Key;
if(zinv >= zinv2)
{
x=(pedge->x+0xFFFF)>>16;
pspan->count=x-psurf2->visxstart;
if(pspan->count > 0)
{
pspan->y =y;
pspan->x =psurf2->visxstart;
pspan->RFlag =psurf2->RFlag;
pspan->color =psurf2->color;
sstemp =&SpanFaces[psurf2->sfIdx];
if(!sstemp->head)
{
sstemp->head =pspan;
}
else if(sstemp->cur)
{
sstemp->cur->next =pspan;
}
pspan->next =NULL;
sstemp->cur =pspan;
if(pspan < &spanz[MAX_SPANS])
pspan++;
}
psurf->visxstart =x;
psurf->pnext =psurf2;
psurf2->pprev =psurf;
SurfStack.pnext =psurf;
psurf->pprev =&SurfStack;
}
else
{
do
{
psurf2 =psurf2->pnext;
zinv2 =psurf2->Key;
} while(zinv < zinv2);
psurf->pnext =psurf2;
psurf->pprev =psurf2->pprev;
psurf2->pprev->pnext=psurf;
psurf2->pprev =psurf;
}
}
}
else
{
if(--psurf->state==0)
{
if(SurfStack.pnext==psurf)
{
x=((pedge->x+0xFFFF)>>16);
pspan->count=x-psurf->visxstart;
if(pspan->count > 0)
{
pspan->y =y;
pspan->x =psurf->visxstart;
pspan->color =psurf->color;
pspan->RFlag =psurf->RFlag;
sstemp =&SpanFaces[psurf->sfIdx];
if(!sstemp->head)
{
sstemp->head =pspan;
}
else if(sstemp->cur)
{
sstemp->cur->next =pspan;
}
pspan->next =NULL;
sstemp->cur =pspan;
if(pspan < &spanz[MAX_SPANS])
pspan++;
}
psurf->pnext->visxstart=x;
}
psurf->pnext->pprev =psurf->pprev;
psurf->pprev->pnext =psurf->pnext;
}
}
}
pedge = Cam->RemoveEdges[y];
while(pedge)
{
pedge->pprev->pnext =pedge->pnext;
pedge->pnext->pprev =pedge->pprev;
pedge =pedge->pnextremove;
}
for(pedge=edgeHead.pnext;pedge!=&edgeTail; )
{
ptemp = pedge->pnext;
pedge->x+=pedge->xstep;
while(pedge->x < pedge->pprev->x)
{
pedge2 =pedge->pprev;
pedge2->pnext =pedge->pnext;
pedge->pnext->pprev =pedge2;
pedge2->pprev->pnext=pedge;
pedge->pprev =pedge2->pprev;
pedge->pnext =pedge2;
pedge2->pprev =pedge;
}
pedge=ptemp;
}
}
pspan->x=-1; // mark the end of the list
}
uint16 FPUCW, OldFPUCW;
void SetFPU24(void)
{
_asm
{
fstcw [OldFPUCW] ; store copy of CW
mov ax, OldFPUCW ; get it in ax
and eax,0xFFFFFCFF
mov [FPUCW],ax
fldcw [FPUCW] ; load the FPU
}
}
void RestoreFPU(void)
{
_asm fldcw [OldFPUCW] ; restore the FPU
}
#pragma warning
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -