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

📄 render.cpp

📁 3D游戏场景编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************************/
/*  render.c                                                                            */
/*                                                                                      */
/*  Author:       Jim Mischel, Ken Baird, Jeff Lomax, Eli Boling                        */
/*  Description:  Tons of render stuff                                                  */
/*                                                                                      */
/*  The contents of this file are subject to the Genesis3D Public License               */
/*  Version 1.01 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.genesis3d.com                                                            */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Genesis3D, released March 25, 1999.                            */
/*Genesis3D Version 1.1 released November 15, 1999                            */
/*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
/*                                                                                      */
/*  Prepared for GenEdit-Classic ver. 0.5, Dec. 15, 2000								*/
/****************************************************************************************/

/*
Code fragments from Chris Hecker's texture mapping articles used with
permission.  http://www.d6.com/users/checker 
*/
#include "stdafx.h"
#include "Globals.h"
#include "render.h"
#include "node.h"
#include "basetype.h"
#include "units.h"
//#include "consoletab.h"
#include "ram.h"
#include "bitmap.h"

#include <math.h>
#include <assert.h>
#include <float.h>


#pragma warning (disable:4725)  // FDIV warning...whoopee!!

static void	Render_LineZBuffer(int xa, int ya, geFloat za,
							   int xb, int yb, geFloat zb,
							   uint16 color, ViewVars *Cam);

static void	Render_Line(int xa, int ya,
						int xb, int yb,
						uint16 color, ViewVars *Cam);

static const geVec3d	VecOrigin	={ 0.0f, 0.0f, 0.0f };
#define MAX_SPANS           100000
#define MAX_SURFS           100000
#define MAX_EDGES           100000
#define	ON_EPSILON			((geFloat)0.02)
//need to put this somewhere
#define	VectorToSUB(a, b)			(*((((geFloat *)(&a))) + (b)))

//screenspace deltas needed by the asm raster code
typedef struct GradientsTag
{
	geFloat dOneOverZdX, dOneOverZdX16;	// d(1/z)/dX
	geFloat dUOverZdX, dUOverZdX16;		// d(u/z)/dX
	geFloat dVOverZdX, dVOverZdX16;		// d(v/z)/dX
} Gradients;

typedef struct EdgeAsmTag
{
	long		X, XStep, Y;	// DDA info
	geFloat	OneOverZ, UOverZ, VOverZ;
} EdgeAsm;

typedef struct SpanTag
{
	int			x, y, count, color, RFlag;
	geFloat	zinvLeft, zinvuLeft, zinvvLeft;
	geFloat	zinvRight, zinvuRight, zinvvRight;
	struct		SpanTag	*next;
} Span;

typedef struct SurfTag
{
	struct	SurfTag	*pnext, *pprev;
	int		color, visxstart;
	int		state, Key, sfIdx, RFlag;
} Surf;

typedef struct EdgeTag
{
	int		x, xstep, leading, Key;
    Surf	*psurf;
    struct	EdgeTag	*pnext, *pprev, *pnextremove;
} Edge;

//For clipping and drawing
typedef struct RenderFaceTag
{
	int32		NumPoints;
	geVec3d		Points[32];
} RenderFace;

typedef struct ViewVarsTag
{
	struct
	{
		BITMAPINFOHEADER	bmiHeader;
		RGBQUAD				bmiColors[256];
	} ViewBMI;

	HBITMAP		hDibSec;
	uint32		Flags;
	uint8		*pBits;
	uint32		*pZBuffer;
	uint32		ViewType;
	geFloat	ZoomFactor;//, GridInterval;

	geVec3d		Vpn, Vright, Vup, CamPos;
	geFloat	roll, pitch, yaw;
	Plane		FrustPlanes[4];
	geFloat	MaxScreenScaleInv, FieldOfView;
	geFloat	XCenter, YCenter, MaxScale;
	geFloat	SpeedScale, YScreenScale, XScreenScale;
	long		Width, Height;
	SizeInfo	*WadSizes;
	Edge		*NewEdges, **RemoveEdges;
	long		FacesDone;
} ViewVars;

geFloat Render_ComputeGridDist (const ViewVars *v, int GridType)
{
	geVec3d left, right;
	float dist;

	// determine grid size for minimum 10 pixels between grid lines
	Render_ViewToWorld (v, 0, 0, &left);
	Render_ViewToWorld (v, 10, 0, &right);
	switch (v->ViewType)
	{
		case VIEWTOP :
			dist = right.X - left.X;
			break;
		case VIEWFRONT :
			dist = right.X - left.X;
			break;
		case VIEWSIDE :
			dist = right.Z - left.Z;
			break;
		default :
			dist = 0.0f;
#if 1
			/*
			  This function should be called only by ortho views.
			  Currently, all views call it so this assertion will cause a problem.
			  Need to fix this...
			*/
			#pragma message ("This function should not be called by non-ortho views.")
#else
			assert (0);
#endif			
			break;
	}

	dist = (float)fabs (dist);
	if (dist < 1.0f)
		dist = 1.0f;
	if (GridType == GRID_TYPE_METRIC)
	{
		dist *= 2.54f;
	}
	return dist;
}

static geFloat log2 (geFloat f)
{
	return (geFloat)(log (f)/log (2.0f));
}

geFloat	Render_GetFineGrid(const ViewVars *v, int GridType)
{
	float dist;
	double Interval;

	assert(v);

	dist = Render_ComputeGridDist (v, GridType);

	switch (GridType)
	{
		case GRID_TYPE_METRIC :
			Interval = pow (10, (int)(log10 (dist)));
			break;
		case GRID_TYPE_TEXEL :
			Interval = pow (2, (int)(log2 (dist)));
			break;
		default :
			assert (0);
			Interval = 1.0f;
			break;
	}
	return (geFloat)Interval;
}

geFloat	Render_GetZoom(const ViewVars *v)
{
	assert(v);

	return	v->ZoomFactor;
}

geFloat	Render_GetXScreenScale(const ViewVars *v)
{
	assert(v);

	return	v->XScreenScale;
}

int	Render_GetInidx(const ViewVars *v)
{
	assert(v);

	return	(v->ViewType>>3)&0x3;
}

int	Render_GetViewType(const ViewVars *v)
{
	assert(v);

	return	v->ViewType;
}

int	Render_GetWidth(const ViewVars *v)
{
	assert(v);

	return	v->Width;
}

int	Render_GetHeight(const ViewVars *v)
{
	assert(v);

	return	v->Height;
}

void	Render_GetCameraPos(const ViewVars *v, geVec3d *pos)
{
	assert(v);
	assert(pos);

	geVec3d_Copy(&v->CamPos, pos);
}

void	Render_GetPitchRollYaw( const ViewVars * v, geVec3d * pPRY )
{
	assert( v ) ;
	assert( pPRY ) ;

	pPRY->X = v->pitch ;
	pPRY->Y = v->yaw ;
	pPRY->Z = v->roll ;
}


geBoolean Render_UpIsDown (const ViewVars *v)
{
	return ((v->pitch < M_PI/2.0f) || (v->pitch > 3.0f*M_PI/2.0f));
}

SizeInfo	*Render_GetWadSizes(const ViewVars *v)
{
	assert(v);

	return	v->WadSizes;
}

void	Render_SetWadSizes(ViewVars *v, SizeInfo *ws)
{
	assert(v);

	v->WadSizes	=ws;
}

void	Render_SetZoom(ViewVars *v, const geFloat zf)
{
	assert(v);

	v->ZoomFactor	=zf;
	// compute grid interval here...
	// we'll have to know if we're metric or texel.
}

void	Render_SetViewType(ViewVars *v, const int vt)
{
	assert(v);

	v->ViewType	=vt;
}

static geFloat Render_NormalizeAngle (float Rads)
{
	geFloat NewAngle;
	
	// first make it in the range -2PI..2PI
	NewAngle = (float)fmod (Rads, 2*M_PI);

	// and then convert to 0..2PI
	if (NewAngle < 0.0f)
	{
		NewAngle += 2*M_PI;
	}
	return NewAngle;	
}

void	Render_SetPitchRollYaw( ViewVars * v, const geVec3d * pPRY )
{
	assert( v ) ;
	assert( pPRY ) ;

	v->pitch	= Render_NormalizeAngle (pPRY->X) ;
	v->yaw		= Render_NormalizeAngle (pPRY->Y) ;
	v->roll		= Render_NormalizeAngle (pPRY->Z) ;
}



ViewVars	*Render_AllocViewVars(void)
{
	ViewVars	*v;

	v	=(ViewVars *) geRam_Allocate(sizeof(ViewVars));
	
	if(!v)
//		ConPrintf("WARNING:  Allocation failure in Render_AllocViewVars()\n"); // old gedit
		CGlobals::GetActiveDocument()->mpMainFrame->ConPrintf("WARNING:  Allocation failure in Render_AllocViewVars()\n"); // new g3dc

	memset(v, 0, sizeof(ViewVars));

	return	v;
}

void	Render_FreeViewVars(ViewVars *v)
{
	assert(v);

	if(v->NewEdges)
	{
		geRam_Free (v->NewEdges);
		v->NewEdges = NULL;
	}

	if(v->RemoveEdges)
	{
		geRam_Free (v->RemoveEdges);
		v->NewEdges = NULL;
	}

	if(v->Flags & DIBDONE)
	{
		DeleteObject(v->hDibSec);
		v->hDibSec = NULL;
	}
	if (v->pZBuffer != NULL)
	{
		geRam_Free (v->pZBuffer);
		v->pZBuffer = NULL;
	}
}

void	Render_SetCameraPos(ViewVars *v, const geVec3d *pos)
{
	assert(v);

	geVec3d_Copy(pos, &v->CamPos);
}

void	Render_ZoomChange(ViewVars *v, const geFloat factor)
{
	geFloat NewZoom;
	geFloat dist;

	assert(v);

	NewZoom = v->ZoomFactor * (1.0f + factor);

	dist = NewZoom * (geFloat)v->Width;
	if (((dist < 1.0f) && (NewZoom < v->ZoomFactor)) ||
		((dist > 100000.0f) && (NewZoom > v->ZoomFactor)))
	{
		// either way too small or way too big,
		// and trying to make it worse
		MessageBeep ((UINT)-1);
	}
	else
	{
		v->ZoomFactor = NewZoom;
	}
}

void	Render_MoveCamPos(ViewVars *v, const geVec3d *dv)
{
	assert(v);
	assert(dv);

	geVec3d_AddScaled (&v->CamPos, &v->Vright, dv->X, &v->CamPos);
	geVec3d_AddScaled (&v->CamPos, &v->Vup, dv->Y, &v->CamPos);
	geVec3d_AddScaled (&v->CamPos, &v->Vpn, dv->Z, &v->CamPos);
}

void	Render_MoveCamPosOrtho(ViewVars *v, const geVec3d *dv)
{
	assert(v);
	assert(dv);

	geVec3d_Add(&v->CamPos, dv, &v->CamPos);
}

void	Render_IncrementYaw(ViewVars *v, const geFloat YawIncr)
{
	assert(v);

	//this would be a nice place to put a range validation
	v->yaw	= Render_NormalizeAngle (v->yaw + (v->MaxScreenScaleInv * YawIncr));
}

void	Render_IncrementPitch(ViewVars *v, const geFloat PitchIncr)
{
	assert(v);

	//this would be a nice place to put a range validation
	v->pitch = Render_NormalizeAngle (v->pitch + (v->MaxScreenScaleInv * PitchIncr));
}

void	Render_IncrementRoll(ViewVars *v, const geFloat RollIncr)
{
	assert(v);

	//this would be a nice place to put a range validation
	v->roll	= Render_NormalizeAngle (v->roll + (v->MaxScreenScaleInv * RollIncr));
}

typedef struct SpanSurfaceTag
{
	Gradients	Grads;
	geFloat	zinv00, zinvu00, zinvv00;
	geFloat	zinvstepy, zinvustepy, zinvvstepy;
	Span		*head, *cur;
	SizeInfo	sizes;
} SpanSurface;

//global things
static	Edge		MaxEdge		={0x6FFFFFFF};
static	Edge		edgeHead, edgeTail;
static	Surf		SurfStack, *pAvailSurf;
static	Edge		*pAvailEdge;
static	SpanSurface	SpanFaces[MAX_SURFS];
static	Span		spanz[MAX_SPANS];
static	Edge		edgez[MAX_EDGES];
static	Surf		surfz[MAX_SURFS];
static	geFloat const Magic	=12582912.0f;

//These are built and tossed... I use vecs for everything
static	geFloat		mRoll[3][3], mPitch[3][3], mYaw[3][3];
static	geVec3d		XAxis={ 1.0, 0.0, 0.0 };
static	geVec3d		YAxis={ 0.0, 1.0, 0.0 };
static	geVec3d		ZAxis={ 0.0, 0.0, 1.0 };

//statics used mainly in asm
static geFloat	FixedScale	=65536.0f;
static geFloat	FixedScale16=4096.0f;		//2^16 / 16
//static geFloat	FixedScale24=16777216.0f;	//2^24
static geFloat	FixedScale28=268435456.0f;	//2^28
static geFloat	One			=1.0f;
static geFloat	geFloatTemp;

static uint32		NumASpans, RemainingCount;
static uint32		DeltaU, DeltaV, DeltaW;
static uint32		UFixed, VFixed, WLeft, WRight;
static uint8		*pTex;
static uint32		*pZBuf;						//32 bit zbuffer

//zcan jump pointers
static unsigned long SCanZ[2];
static unsigned long SCan[2];

//zcan storage area... must be 32 in length
static unsigned long can0[32];


#define SV_ACCELERATE		10.0f
#define SV_FRICTION			8.0f
#define CL_FORWARDSPEED		200.0f
#define CL_SIDESPEED		320.0f
#define CLIP_PLANE_EPSILON	0.001f

static void	DrawScanLine128(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine256(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine64(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine32(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine16(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine128_ZFill(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine256_ZFill(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine64_ZFill(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine32_ZFill(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine16_ZFill(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine128_ZBuf(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

static void	DrawScanLine256_ZBuf(SizeInfo *pSizeInfo,
				  Gradients const *pGradients,
				  EdgeAsm *pLeft,
				  EdgeAsm *pRight);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -