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

📄 utility.cpp

📁 ROAM实时动态LOD地形渲染
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Utility.cpp
// Bryan Turner
//
// Parts of the code in this file were borrowed from numerous public sources &
//   literature.  I reserve NO rights to this code and give a hearty thank-you to all the
//   excellent sources used in this project.  These include, but are not limited to:
//
//   Longbow Digital Arts Programming Forum (www.LongbowDigitalArts.com)
//   Gamasutra Features (www.Gamasutra.com)
//   GameDev References (www.GameDev.net)
//   C. Cookson's ROAM implementation (C.J.Cookson@dcs.warwick.ac.uk OR cjcookson@hotmail.com)
//   OpenGL Super Bible (Waite Group Press)
//   And many more...
//

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gl/gl.h>		// OpenGL
#include <gl/glu.h>		// GLU library

#include "utility.h"
#include "landscape.h"

// Observer and Follower modes
#define FOLLOW_MODE (0)
#define OBSERVE_MODE (1)
#define DRIVE_MODE (2)
#define FLY_MODE (3)

// Perspective & Window defines
#define FOV_ANGLE     (90.0f)
#define NEAR_CLIP     (1.0f)
#define FAR_CLIP      (2500.0f)

// --------------------------------------
// GLOBALS
// --------------------------------------
Landscape gLand;

// Texture
GLuint gTextureID=1;

// Camera Stuff
GLfloat gViewPosition[]		= { 0.f, 5.f, 0.f };
GLfloat gCameraPosition[]	= { 0.f, 0.f, -555.f };
GLfloat gCameraRotation[]	= { 42.f, -181.f, 0.f };
GLfloat gAnimateAngle = 0.f;
GLfloat gClipAngle;

// Misc. Globals
int gAnimating  = 0;
int gRotating  = 0;
int gDrawFrustum = 1;
int gCameraMode = OBSERVE_MODE;
int gDrawMode   = DRAW_USE_TEXTURE;
int gStartX=-1, gStartY;
int gNumTrisRendered;
long gStartTime, gEndTime;
unsigned char *gHeightMap;
unsigned char *gHeightMaster;
int gNumFrames;
float gFovX = 90.0f;

// Beginning frame varience (should be high, it will adjust automatically)
float gFrameVariance = 50;

// Desired number of Binary Triangle tessellations per frame.
// This is not the desired number of triangles rendered!
// There are usually twice as many Binary Triangle structures as there are rendered triangles.
int gDesiredTris = 10000;

// ---------------------------------------------------------------------
// Reduces a normal vector specified as a set of three coordinates,
// to a unit normal vector of length one.
//
void ReduceToUnit(float vector[3])
	{
	float length;
	
	// Calculate the length of the vector		
	length = sqrtf((vector[0]*vector[0]) + 
				   (vector[1]*vector[1]) +
				   (vector[2]*vector[2]));

	// Keep the program from blowing up by providing an exceptable
	// value for vectors that may calculated too close to zero.
	if(length == 0.0f)
		length = 1.0f;

	// Dividing each element by the length will result in a
	// unit normal vector.
	vector[0] /= length;
	vector[1] /= length;
	vector[2] /= length;
	}

// ---------------------------------------------------------------------
// Points p1, p2, & p3 specified in counter clock-wise order
//
void calcNormal(float v[3][3], float out[3])
	{
	float v1[3],v2[3];
	static const int x = 0;
	static const int y = 1;
	static const int z = 2;

	// Calculate two vectors from the three points
	v1[x] = v[0][x] - v[1][x];
	v1[y] = v[0][y] - v[1][y];
	v1[z] = v[0][z] - v[1][z];

	v2[x] = v[1][x] - v[2][x];
	v2[y] = v[1][y] - v[2][y];
	v2[z] = v[1][z] - v[2][z];

	// Take the cross product of the two vectors to get
	// the normal vector which will be stored in out
	out[x] = v1[y]*v2[z] - v1[z]*v2[y];
	out[y] = v1[z]*v2[x] - v1[x]*v2[z];
	out[z] = v1[x]*v2[y] - v1[y]*v2[x];

	// Normalize the vector (shorten length to one)
	ReduceToUnit(out);
	}

// ---------------------------------------------------------------------
// Load the Height Field from a data file
//
void loadTerrain(int size, unsigned char **dest)
{
	FILE *fp;
	char fileName[30];

	// Optimization:  Add an extra row above and below the height map.
	//   - The extra top row contains a copy of the last row in the height map.
	//   - The extra bottom row contains a copy of the first row in the height map.
	// This simplifies the wrapping of height values to a trivial case. 
	gHeightMaster = (unsigned char *)malloc( size * size * sizeof(unsigned char) + size * 2 );
	
	// Give the rest of the application a pointer to the actual start of the height map.
	*dest = gHeightMaster + size;

	sprintf( fileName, "Height%d.raw", size );
	fp = fopen(fileName, "rb");

	// TESTING: READ A TREAD MARKS MAP...
	if ( fp == NULL )
	{
		sprintf( fileName, "Map.ved", size );
		fp = fopen(fileName, "rb");
		if ( fp != NULL )
			fseek( fp, 40, SEEK_SET );	// Skip to the goods...
	}

	if (fp == NULL)
	{
		// Oops!  Couldn't find the file.
		
		// Clear the board.
		memset( gHeightMaster, 0, size * size + size * 2 );
		return;
	}
	fread(gHeightMaster + size, 1, (size * size), fp);
	fclose(fp);

	// Copy the last row of the height map into the extra first row.
	memcpy( gHeightMaster, gHeightMaster + size * size, size );

	// Copy the first row of the height map into the extra last row.
	memcpy( gHeightMaster + size * size + size, gHeightMaster + size, size );
}

// ---------------------------------------------------------------------
// Free the Height Field array
//
void freeTerrain()
{
	if ( gHeightMaster )
		free( gHeightMaster );
}

// ---------------------------------------------------------------------
// Switch GL Contexts when moving between draw modes to improve performance.
//
void SetDrawModeContext()
{
	switch (gDrawMode)
	{
	case DRAW_USE_TEXTURE:
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_TEXTURE_GEN_S);
		glEnable(GL_TEXTURE_GEN_T);
		glPolygonMode(GL_FRONT, GL_FILL);
		break;

	case DRAW_USE_LIGHTING:
		glEnable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glPolygonMode(GL_FRONT, GL_FILL);
		break;

	case DRAW_USE_FILL_ONLY:
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glPolygonMode(GL_FRONT, GL_FILL);
		break;

	default:
	case DRAW_USE_WIREFRAME:
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		glPolygonMode(GL_FRONT, GL_LINE);
		break;
	}
}

// ---------------------------------------------------------------------
// Initialize the ROAM implementation
//
int roamInit(unsigned char *map)
{
	// Perform some bounds checking on the #define statements
	if ( gDesiredTris > POOL_SIZE )
		return -1;

	if ( POOL_SIZE < 100 )
		return -1;

// ----------- TEXTURE INITIALIZATION -----------
	glBindTexture(GL_TEXTURE_2D, gTextureID);
	
	unsigned char *pTexture = (unsigned char *)malloc(TEXTURE_SIZE*TEXTURE_SIZE*3);
	unsigned char *pTexWalk = pTexture;

	if ( !pTexture )
		exit(0);

	// Create a random stipple pattern for the texture.  Only use the Green channel.
	// This could easily be modified to load in a bitmap or other texture source.
	for ( int x = 0; x < TEXTURE_SIZE; x++ )
		for ( int y = 0; y < TEXTURE_SIZE; y++ )
		{
			int color = (int)(128.0+(40.0 * rand())/RAND_MAX);
			if ( color > 255 )  color = 255;
			if ( color < 0 )    color = 0;
			*(pTexWalk++) = 0;
			*(pTexWalk++) = color;	// Only use the Green chanel.
			*(pTexWalk++) = 0;
		}

	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TEXTURE_SIZE, TEXTURE_SIZE, GL_RGB, GL_UNSIGNED_BYTE, pTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

	free(pTexture);

	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

// ----------- LANDSCAPE INITIALIZATION -----------
	gLand.Init(map);

	return 0;
}

// ---------------------------------------------------------------------
// Call all functions needed to draw a frame of the landscape
//
void roamDrawFrame()
{
	// Perform all the functions needed to render one frame.
	gLand.Reset();
	gLand.Tessellate();
	gLand.Render();
}

// ---------------------------------------------------------------------
// Draw a simplistic frustum for debug purposes.
//
void drawFrustum()
{
	//
	// Draw the camera eye & frustum
	//
	glDisable(GL_LIGHTING);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);

	glPointSize(5.f);
	glLineWidth(3.f);

	glBegin(GL_LINES);

		// Draw the View Vector starting at the eye (red)
		glColor3f(1, 0, 0);
		glVertex3f(	gViewPosition[0],
					gViewPosition[1],
					gViewPosition[2] );

		glVertex3f(	gViewPosition[0] + 50.0f * sinf( gClipAngle * M_PI / 180.0f ),
					gViewPosition[1],
					gViewPosition[2] - 50.0f * cosf( gClipAngle * M_PI / 180.0f ));


		// Draw the view frustum (blue)
		glColor3f(0, 0, 1);
		glVertex3f(	gViewPosition[0],
					gViewPosition[1],
					gViewPosition[2] );

		glVertex3f(	gViewPosition[0] + 1000.0f * sinf( (gClipAngle-45.0f) * M_PI / 180.0f ),
					gViewPosition[1],
					gViewPosition[2] - 1000.0f * cosf( (gClipAngle-45.0f) * M_PI / 180.0f ));

		glVertex3f(	gViewPosition[0],
					gViewPosition[1],
					gViewPosition[2] );

		glVertex3f(	gViewPosition[0] + 1000.0f * sinf( (gClipAngle+45.0f) * M_PI / 180.0f ),
					gViewPosition[1],
					gViewPosition[2] - 1000.0f * cosf( (gClipAngle+45.0f) * M_PI / 180.0f ));

		// Draw the clipping planes behind the eye (yellow)
		const float PI_DIV_180 = M_PI / 180.0f;
		const float FOV_DIV_2 = gFovX/2;

		int ptEyeX = (int)(gViewPosition[0] - PATCH_SIZE * sinf( gClipAngle * PI_DIV_180 ));
		int ptEyeY = (int)(gViewPosition[2] + PATCH_SIZE * cosf( gClipAngle * PI_DIV_180 ));

		int ptLeftX = (int)(ptEyeX + 100.0f * sinf( (gClipAngle-FOV_DIV_2) * PI_DIV_180 ));
		int ptLeftY = (int)(ptEyeY - 100.0f * cosf( (gClipAngle-FOV_DIV_2) * PI_DIV_180 ));

		int ptRightX = (int)(ptEyeX + 100.0f * sinf( (gClipAngle+FOV_DIV_2) * PI_DIV_180 ));
		int ptRightY = (int)(ptEyeY - 100.0f * cosf( (gClipAngle+FOV_DIV_2) * PI_DIV_180 ));

		glColor3f(1, 1, 0);
		glVertex3f(	(float)ptEyeX,
					gViewPosition[1],
					(float)ptEyeY );

		glVertex3f(	(float)ptLeftX,
					gViewPosition[1],
					(float)ptLeftY);

		glVertex3f(	(float)ptEyeX,
					gViewPosition[1],
					(float)ptEyeY );

		glVertex3f(	(float)ptRightX,
					gViewPosition[1],
					(float)ptRightY);

	glEnd();

	glLineWidth(1.f);

⌨️ 快捷键说明

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