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

📄 graphics.c

📁 著名物理引擎Hawk的源代码
💻 C
字号:
/* graphics.c, HAWK game engine
 *
 * This is the entry to the 3D specific routines.
 *
 * Copyright 1997-1998 by Phil Frisbie, Jr.
 * for Hawk Software
 *
 */

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <gl/gl.h>
#include "hawk.h"
#include "internal.h"
#include "bmp.h"
#include "particle.h"
#include "graphics.h"

float	modelmatrix[16];

GLubyte pointTex[] =
{
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,  64,  64,  64,  64, 128, 128, 128, 128, 128, 128, 128, 128,  64,  64,  64,  64,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 128, 128, 128, 128,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 128, 128, 128, 128,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,  64,  64,  64,  64, 128, 128, 128, 128, 128, 128, 128, 128,  64,  64,  64,  64,   0,   0,   0,   0,   0,   0,   0,   0};

/*
 * Check name in the GL_EXTENSIONS string
 *
 * Returns TRUE if found
 */

BOOL checkEXT(char *name)
{
	int	len = strlen(name);
	char	*list = (char *)glGetString(GL_EXTENSIONS);

	while(*list)
	{
		if(strncmp(list, name, len) == 0)
			return TRUE;
		while(*list && !isspace(*list))
			++list;
		while(*list && isspace(*list))
			++list;
	}
	return FALSE;
}

#ifdef WIN32
static void (APIENTRY *glPointParameterfWIN)(GLenum pname, GLfloat param);
static void (APIENTRY *glPointParameterfvWIN)(GLenum pname, const GLfloat *params);
#endif

#ifndef GL_EXT_point_parameters
#define GL_POINT_SIZE_MIN_EXT				0x8126
#define GL_POINT_SIZE_MAX_EXT				0x8127
#define	GL_POINT_FADE_THRESHOLD_SIZE_EXT	0x8128
#define	GL_DISTANCE_ATTENUATION_EXT			0x8129
#endif


/*
 * Main init code, must be called before any other graph* function
 *
 * Return TRUE when done, no failure at this time
 */

BOOL graphInit(void)
{
	char	*ext;
//	GLfloat attenuation[3] = { 0.0f, 0.2f, 0.0f };
	GLfloat attenuation[3] = { 0.0f, 0.2f, 0.0f };

/* init any arrays, vars, etc. */
	Engine.GLvendor = (char *)glGetString(GL_VENDOR);
	Engine.GLrenderer = (char *)glGetString(GL_RENDERER);
	Engine.pointEXT = checkEXT("GL_EXT_point_parameters");
	Engine.multitexEXT = checkEXT("GL_ARB_multitexture");
	ext = (char *)glGetString(GL_EXTENSIONS);
	logf("Extensions: %s\n", ext);

/* init OpenGL environment */
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glDrawBuffer(GL_BACK);

	glEnable(GL_TEXTURE_2D);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glPointSize(16.0);
	glEnable(GL_POINT_SMOOTH);

	if(Engine.pointEXT)
	{
#ifdef WIN32
		glPointParameterfWIN = (void *)wglGetProcAddress("glPointParameterfEXT");
		glPointParameterfvWIN = (void *)wglGetProcAddress("glPointParameterfvEXT");
		if(!glPointParameterfWIN || !glPointParameterfvWIN)
		{
			Engine.pointEXT = FALSE;
			Engine.pointtex = texBuildTex(RGBA_TEXTURE, 8, 8, pointTex);
		}
		else
		{
			glPointParameterfvWIN(GL_DISTANCE_ATTENUATION_EXT, attenuation);
//			glPointParameterfWIN(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 2.0);
//			glPointParameterfWIN(GL_POINT_SIZE_MIN_EXT, 2.0);
		}
#else
#ifdef GL_EXT_point_parameters
		glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, linear);
		glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0);
		glPointParameterfEXT(GL_POINT_SIZE_MIN_EXT, 2.0);
#endif
#endif
	}
	else /* create point texture */
	{
		Engine.pointtex = texBuildTex(RGBA_TEXTURE, 8, 8, pointTex);
	}
	return TRUE;
}

/*
 * called to shutdown graphics
 */

void graphStop(void)
{
}

/*
 * Enable/disable Z-buffer
 */

void graphDepthTest(BOOL a)
{
	if(a)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);
}

/*
 * Set the depth function
 */

void graphDepthFunc(int f)
{
	glDepthFunc(f);
}

/*
 * Enable/disable blending
 */

void graphBlend(BOOL a)
{
	if(a)
		glEnable(GL_BLEND);
	else
		glDisable(GL_BLEND);
}

/*
 * Set the blend function
 */

void graphBlendFunc(int s, int d)
{
	glBlendFunc(s, d);
}

/*
 * Enable/disable texturing
 */

void graphTexture(BOOL a)
{
	if(a)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);
}

/*
* Set the texture function
*/

void graphTextureFunc(int f)
{
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, f);
}

/*
* Enable/disable texturing
*/

void graphAlpha(BOOL a)
{
	if(a)
		glEnable(GL_ALPHA_TEST);
	else
		glDisable(GL_ALPHA_TEST);
}

/*
* Set the alpha test function
*/

void graphAlphaFunc(int f, float v)
{
	glAlphaFunc(f, v);
}

/*
* Returns the next texture number
*/

int graphNextTex(void)
{
	static	GLuint	tex = 1;

/*	glGenTextures(1, &tex); */

	return tex++;
}

/*
* Use the tex texture
*/

void graphUseTexture(int tex)
{
	glBindTexture(GL_TEXTURE_2D, tex);
}

/*
* Use color for blends
*/
void graphUseColor(unsigned char r, unsigned char g,
				   unsigned char b, unsigned char a)
{
	glColor4ub(r, g, b, a);
}

/*
* Set the texture wrap mode
*/

void graphSetTexWrap(BOOL wrap)
{
	if(wrap)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	}
	else
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	}
}

/*
* Set the texture filtering mode. Called when loading textures.
*/

void graphSetTexFilter(BOOL mipmap)
{
	if(mipmap)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	}
	else
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

/*
* Returns the max texture size for the hardware
*/

int graphGetMaxTexSize(void)
{
	int maxsize;

	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);

	return maxsize;
}

/*
* Creates a texture
*/

void graphCreateTex(int level, int components, int w, int h, unsigned char *image)
{

	glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
}

char basename[] = "hawkshot";

/*
* Dumps the front buffer to a 24 bit BMP file
*/

void graphCaptureScreen(void)
{
	static int	count = 0;
	char		file[1024];
	int			length;
	int			i, w, h;
	char		*buffer;
	BMP_HEADER	*bmp;

	if(!count)	/* init count to next free filename */
	{
		do
		{
			count++;
			sprintf(file, "%s%d.bmp", basename, count);
		}while(fileSize(file));
	}
	else
	{
		count++;
		sprintf(file, "%s%d.bmp", basename, count);
	}
	w = Engine.w - Engine.w%4;
	h = Engine.h;
	length = w * h * 3;
	buffer = TempMalloc(length + sizeof(BMP_HEADER) - 1);
	bmp = (BMP_HEADER *)buffer;
	bmp->type = 0x4D42;	/* BM */
	bmp->fsize = 54 + length;
	bmp->reserved1 = 0;
	bmp->reserved2 = 0;
	bmp->offBits = 54;
	bmp->hsize = 40;
	bmp->width = w;
	bmp->height = h;
	bmp->planes = 1;
	bmp->bitCount = 24;
	bmp->compression = 0;
	bmp->sizeImage = length;
	bmp->XPelsPerMeter = 0;
	bmp->YPelsPerMeter = 0;
	bmp->ClrUsed = 0;
	bmp->ClrImportant = 0;
	glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, bmp->data);
	for(i=0;i<length;i+=3)	/* convert RGB to BGR Windows format */
	{
		unsigned char t = bmp->data[i];

		bmp->data[i] = bmp->data[i+2];
		bmp->data[i+2] = t;
	}
	length += sizeof(BMP_HEADER) - 1;
	saveFile(file, length, buffer);
	TempFree(buffer);
}

/*
* Sets up a perspective viewport
*/

void graphSetViewport(float angle, int x, int y, int w, int h)
{
	float xmin, xmax, ymin, ymax, ratio,
			zNear = 5.0, zFar = 5000.0;

	ymax = zNear * tan(angle * (float)M_PI / 360.0);
	ymin = -ymax;

	if(w>h)
		ratio = w / h;
	else
		ratio = h / w;

	xmin = ymin * ratio;
	xmax = ymax * ratio;

	glViewport(x, y, w, h);
	glMatrixMode(GL_PROJECTION);
	glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}

void graphLookAt(float eyex, float eyey, float eyez,
			float centerx, float centery, float centerz,
			float upx, float upy, float upz)
{
	float	m[16];
	float	x[3], y[3], z[3];
	float	mag;

	glMatrixMode(GL_MODELVIEW);
	/* Make rotation matrix */

	/* Z vector */
	z[0] = eyex - centerx;
	z[1] = eyey - centery;
	z[2] = eyez - centerz;
	mag = sqrt( z[0]*z[0] + z[1]*z[1] + z[2]*z[2] );
	if (mag)
	{
		z[0] /= mag;
		z[1] /= mag;
		z[2] /= mag;
	}

	/* Y vector */
	y[0] = upx;
	y[1] = upy;
	y[2] = upz;

	/* X vector = Y cross Z */
	x[0] =  y[1]*z[2] - y[2]*z[1];
	x[1] = -y[0]*z[2] + y[2]*z[0];
	x[2] =  y[0]*z[1] - y[1]*z[0];

	/* Recompute Y = Z cross X */
	y[0] =  z[1]*x[2] - z[2]*x[1];
	y[1] = -z[0]*x[2] + z[2]*x[0];
	y[2] =  z[0]*x[1] - z[1]*x[0];

	/* cross product gives area of parallelogram, which is < 1.0 for
	* non-perpendicular unit-length vectors; so normalize x, y here
	*/

	mag = sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] );
	if (mag)
	{
		x[0] /= mag;
		x[1] /= mag;
		x[2] /= mag;
	}

	 mag = sqrt( y[0]*y[0] + y[1]*y[1] + y[2]*y[2] );
	if (mag)
	{
		y[0] /= mag;
		y[1] /= mag;
		y[2] /= mag;
	}

#define M(row,col)  m[col*4+row]
	M(0,0) = x[0];  M(0,1) = x[1];  M(0,2) = x[2];  M(0,3) = 0.0;
	M(1,0) = y[0];  M(1,1) = y[1];  M(1,2) = y[2];  M(1,3) = 0.0;
	M(2,0) = z[0];  M(2,1) = z[1];  M(2,2) = z[2];  M(2,3) = 0.0;
	M(3,0) = 0.0;   M(3,1) = 0.0;   M(3,2) = 0.0;   M(3,3) = 1.0;
#undef M
	glMultMatrixf(m);

	glTranslatef(-eyex, -eyey, -eyez);

	glGetFloatv(GL_MODELVIEW_MATRIX, modelmatrix);
}

void graphBegin2D(void)
{
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
	glViewport(0, 0, Engine.w, Engine.h);
	glMatrixMode(GL_PROJECTION);
	glOrtho(0.0, Engine.w, 0.0, Engine.h, -1.0, 1.0 );
	glMatrixMode(GL_MODELVIEW);
}

/*
* Rotate an object
*/

void graphRotate(float angle, float x, float y, float z)
{
	glMatrixMode(GL_MODELVIEW);
	glRotatef(angle, x, y, z);
}

/*
* Scale an object
*/

void graphScale(float x, float y, float z)
{
	glMatrixMode(GL_MODELVIEW);
	glScalef(x, y, z);
}

/*
* Translate an object
*/

void graphTranslate(float x, float y, float z)
{
	glMatrixMode(GL_MODELVIEW);
	glTranslatef(x, y, z);
}

/*
* Generic draw function for most level surfaces
*/

void graphDraw(int mode, TPOINT *points, int start, int number)
{
	int	i;
	TPOINT	*p = &points[start];


	glBegin(mode);
	for(i=0;i<number;i++)
	{
		glTexCoord2fv(p[i].t);
		glVertex3fv(p[i].v);
	}
	glEnd();
}

/*
* Special draw function for surface lightmaps
*/

void graphDrawLightmap(int mode, TPOINT *points, int start, int number)
{
	int	i;
	TPOINT	*p = &points[start];


	glBegin(mode);
	for(i=0;i<number;i++)
	{
		glTexCoord2fv(p[i].lm);
		glVertex3fv(p[i].v);
	}
	glEnd();
}

/*
* Special draw function for particles
*/

void graphDrawParticles(void)
{
	/* for now, just draw all particles in the level */
		PARTICLE	*p;

		p = firstparticle;
		glColor3f(1.0, 1.0, 1.0);

		if(Engine.pointEXT)
		{
			vec_t lastsize = p->size;

			glAlphaFunc(GL_GREATER, 0.5f);
			glEnable(GL_ALPHA_TEST);
			glEnable(GL_BLEND);
			glDisable(GL_TEXTURE_2D);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glPointSize(lastsize);
			glBegin(GL_POINTS);
			do
			{
				if(lastsize != p->size)
				{
					glEnd();
					lastsize = p->size;
					glPointSize(lastsize);
					glBegin(GL_POINTS);
				}
				glColor3fv(p->color);
				glVertex3fv(p->center);
				p = p->next;
			}while(p);
			glEnd();
			glDisable(GL_ALPHA_TEST);
		}
		else
		{
			vec3_t	tv, rv, lv, top;
			vec_t	angle = GLevel.view[0]->hangle + GLevel.view[0]->object->angles[Z] + 90.0;
			vec_t	pitch = GLevel.view[0]->object->pitch;
			vec_t	x, y, temp;

			x = cos(RAD(angle));
			y = sin(RAD(angle));
			temp = cos(RAD(pitch + 90.0));
			top[X] = y * temp;
			top[Y] = x * temp;
			top[Z] = sin(RAD(pitch + 90.0));
			VectorNormalize(top, top);
			x *= 0.5;
			y *= 0.5;

			/* setup to render the translucent particles */
			glEnable(GL_BLEND);
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, Engine.pointtex);
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			glAlphaFunc(GL_GREATER, 0.5f);
			glEnable(GL_ALPHA_TEST);

			glBegin(GL_TRIANGLES);
			do
			{
				vec_t size;
				if(p->solid)
				{
					p = p->next;
					continue;
				}
				size = p->size / 16;
				glColor3fv(p->color);
				VectorCopy(p->center, tv);
				VectorCopy(tv, rv);
				VectorCopy(tv, lv);
				tv[X] += top[X] * size;
				tv[Y] -= top[Y] * size;
				tv[Z] += top[Z] * size;
				rv[X] += x * size;
				rv[Y] += y * size;
				lv[X] -= x * size;
				lv[Y] -= y * size;
				glTexCoord2f(0.5, 0.2);
				glVertex3fv(tv);
				glTexCoord2f(0.0, 1.0);
				glVertex3fv(lv);
				glTexCoord2f(1.0, 1.0);
				glVertex3fv(rv);
				p = p->next;
			}while(p);
			glEnd();


			/* setup to render solid particles */
			glDisable(GL_BLEND);
			p = firstparticle;

			glBegin(GL_TRIANGLES);
			do
			{
				vec_t size;
				if(!p->solid)
				{
					p = p->next;
					continue;
				}
				size = p->size / 16;
				glColor3fv(p->color);
				VectorCopy(p->center, tv);
				VectorCopy(tv, rv);
				VectorCopy(tv, lv);
				tv[X] += top[X] * size;
				tv[Y] -= top[Y] * size;
				tv[Z] += top[Z] * size;
				rv[X] += x * size;
				rv[Y] += y * size;
				lv[X] -= x * size;
				lv[Y] -= y * size;
				glTexCoord2f(0.5, 0.2);
				glVertex3fv(tv);
				glTexCoord2f(0.0, 1.0);
				glVertex3fv(lv);
				glTexCoord2f(1.0, 1.0);
				glVertex3fv(rv);
				p = p->next;
			}while(p);
			glEnd();

			graphAlpha(FALSE);
		}
}

void graphClearBuffers(int buffer)
{
	glClear(buffer);
}

void graphSetClearColor(unsigned char r, unsigned char g,
				   unsigned char b, unsigned char a)
{
	glClearColor(r, g, b, a);
}

void graphClearMatrix(int m)
{
	if(m&MODEL_MATRIX)
	{
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
	}
	if(m&PROJECTION_MATRIX)
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
	}
}

void graphBeginObject(void)
{
	glLoadMatrixf(modelmatrix);
}

⌨️ 快捷键说明

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