📄 render.cpp
字号:
/****************************************************************************************/
/* 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 + -