⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render.cpp

📁 3D游戏场景编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
					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 + -