📄 md2.cpp
字号:
#include "stdafx.h"
#include "md2.h"
#include <windows.h> // standard Windows app include
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gl/gl.h> // standard OpenGL include
#include <gl/glu.h>
HDC g_HDC; // global device context
#define BITMAP_ID 0x4D42 // the universal bitmap ID
#define PI 3.14159
modelData_t *myModel;
modelData_t *gunModel;
modelData_t *myModel2;
modelData_t *gunModel2;
modelData_t *myModel3;
modelData_t *gunModel3;
float angle = 0.0f; // camera angle
float radians = 0.0f; // camera angle in radians
////// Mouse/Camera Variables
int mouseX, mouseY; // mouse coordinates
float cameraX, cameraY, cameraZ; // camera coordinates
float lookX, lookY, lookZ; // camera look-at coordinates
void FreeModel(modelData_t *model)
{
if (model->triIndex != NULL)
free(model->triIndex);
if (model->pointList != NULL)
free(model->pointList);
if (model->st != NULL)
free(model->st);
if (model != NULL)
free(model);
}
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
unsigned int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
// LoadPCXFile()
// desc: loads a PCX file into memory
unsigned char *LoadPCXFile(char *filename, PCXHEADER *pcxHeader)
{
int idx = 0; // counter index
int c; // used to retrieve a char from the file
int i; // counter index
int numRepeat;
FILE *filePtr; // file handle
int width; // pcx width
int height; // pcx height
unsigned char *pixelData; // pcx image data
unsigned char *paletteData; // pcx palette data
// open PCX file
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// retrieve first character; should be equal to 10
c = getc(filePtr);
if (c != 10)
{
fclose(filePtr);
return NULL;
}
// retrieve next character; should be equal to 5
c = getc(filePtr);
if (c != 5)
{
fclose(filePtr);
return NULL;
}
// reposition file pointer to beginning of file
rewind(filePtr);
// read 4 characters of data to skip
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
// retrieve leftmost x value of PCX
pcxHeader->xMin = fgetc(filePtr); // loword
pcxHeader->xMin |= fgetc(filePtr) << 8; // hiword
// retrieve bottom-most y value of PCX
pcxHeader->yMin = fgetc(filePtr); // loword
pcxHeader->yMin |= fgetc(filePtr) << 8; // hiword
// retrieve rightmost x value of PCX
pcxHeader->xMax = fgetc(filePtr); // loword
pcxHeader->xMax |= fgetc(filePtr) << 8; // hiword
// retrieve topmost y value of PCX
pcxHeader->yMax = fgetc(filePtr); // loword
pcxHeader->yMax |= fgetc(filePtr) << 8; // hiword
// calculate the width and height of the PCX
width = pcxHeader->xMax - pcxHeader->xMin + 1;
height = pcxHeader->yMax - pcxHeader->yMin + 1;
// allocate memory for PCX image data
pixelData = (unsigned char*)malloc(width*height);
// set file pointer to 128th byte of file, where the PCX image data starts
fseek(filePtr, 128, SEEK_SET);
// decode the pixel data and store
while (idx < (width*height))
{
c = getc(filePtr);
if (c > 0xbf)
{
numRepeat = 0x3f & c;
c = getc(filePtr);
for (i = 0; i < numRepeat; i++)
{
pixelData[idx++] = c;
}
}
else
pixelData[idx++] = c;
fflush(stdout);
}
// allocate memory for the PCX image palette
paletteData = (unsigned char*)malloc(768);
// palette is the last 769 bytes of the PCX file
fseek(filePtr, -769, SEEK_END);
// verify palette; first character should be 12
c = getc(filePtr);
if (c != 12)
{
fclose(filePtr);
return NULL;
}
// read and store all of palette
for (i = 0; i < 768; i++)
{
c = getc(filePtr);
paletteData[i] = c;
}
// close file and store palette in header
fclose(filePtr);
pcxHeader->palette = paletteData;
// return the pixel image data
return pixelData;
}
// LoadPCXTexture()
// desc: loads a PCX image file as a texture
texture_t *LoadPCXTexture(char *filename)
{
PCXHEADER texInfo; // header of texture
texture_t *thisTexture; // the texture
unsigned char *unscaledData;// used to calculate pcx
int i; // index counter
int j; // index counter
int width; // width of texture
int height; // height of texture
// allocate memory for texture struct
thisTexture = (texture_t*)malloc(sizeof(texture_t));
if (thisTexture == NULL)
return NULL;
// load the PCX file into the texture struct
thisTexture->data = LoadPCXFile(filename, &texInfo);
if (thisTexture->data == NULL)
{
free(thisTexture->data);
return NULL;
}
// store the texture information
thisTexture->palette = texInfo.palette;
thisTexture->width = texInfo.xMax - texInfo.xMin + 1;
thisTexture->height = texInfo.yMax - texInfo.yMin + 1;
thisTexture->textureType = PCX;
// allocate memory for the unscaled data
unscaledData = (unsigned char*)malloc(thisTexture->width*thisTexture->height*4);
// store the unscaled data via the palette
for (j = 0; j < thisTexture->height; j++)
{
for (i = 0; i < thisTexture->width; i++)
{
unscaledData[4*(j*thisTexture->width+i)+0] = (unsigned char)thisTexture->palette[3*thisTexture->data[j*thisTexture->width+i]+0];
unscaledData[4*(j*thisTexture->width+i)+1] = (unsigned char)thisTexture->palette[3*thisTexture->data[j*thisTexture->width+i]+1];
unscaledData[4*(j*thisTexture->width+i)+2] = (unsigned char)thisTexture->palette[3*thisTexture->data[j*thisTexture->width+i]+2];
unscaledData[4*(j*thisTexture->width+i)+3] = (unsigned char)255;
}
}
// find width and height's nearest greater power of 2
width = thisTexture->width;
height = thisTexture->height;
// find width's
i = 0;
while (width)
{
width /= 2;
i++;
}
thisTexture->scaledHeight = (long)pow(2, i-1);
// find height's
i = 0;
while (height)
{
height /= 2;
i++;
}
thisTexture->scaledWidth = (long)pow(2, i-1);
// clear the texture data
if (thisTexture->data != NULL)
{
free(thisTexture->data);
thisTexture->data = NULL;
}
// reallocate memory for the texture data
thisTexture->data = (unsigned char*)malloc(thisTexture->scaledWidth*thisTexture->scaledHeight*4);
// use the GL utility library to scale the texture to the unscaled dimensions
gluScaleImage (GL_RGBA, thisTexture->width, thisTexture->height, GL_UNSIGNED_BYTE, unscaledData, thisTexture->scaledWidth, thisTexture->scaledHeight, GL_UNSIGNED_BYTE, thisTexture->data);
return thisTexture;
}
// LoadBMPTexture()
// desc: loads a texture of the BMP format
texture_t *LoadBMPTexture(char *filename)
{
BITMAPINFOHEADER texInfo; // BMP header
texture_t *thisTexture; // the texture
// allocate memory for the texture
thisTexture = (texture_t*)malloc(sizeof(texture_t));
if (thisTexture == NULL)
return NULL;
// store BMP data in texture
thisTexture->data = LoadBitmapFile(filename, &texInfo);
if (thisTexture->data == NULL)
{
free(thisTexture);
return NULL;
}
// store texture information
thisTexture->width = texInfo.biWidth;
thisTexture->height = texInfo.biHeight;
thisTexture->palette = NULL;
thisTexture->scaledHeight = 0;
thisTexture->scaledWidth = 0;
thisTexture->textureType = BMP;
return thisTexture;
}
// LoadTexture()
// desc: loads a texture given the filename
texture_t *LoadTexture(char *filename)
{
texture_t *thisTexture;
char *extStr;
// get extension from filename
extStr = strchr(filename, '.');
extStr++;
// set the texture type based on extension of filename
if ((strcmp(extStr, "BMP") == 0) || (strcmp(extStr, "bmp") == 0))
thisTexture = LoadBMPTexture(filename);
else if ((strcmp(extStr, "PCX") == 0) || (strcmp(extStr, "pcx") == 0) )
thisTexture = LoadPCXTexture(filename);
/*
else if ((strcmp(extStr, "TGA") == 0) || (strcmp(extStr, "tga") == 0) )
thisTexture = LoadTGATexture(filename);
//texType = TGA;
*/
return thisTexture;
}
// SetupMD2Texture()
// desc: sets up a texture for use with an MD2 model
void SetupMD2Texture(texture_t *thisTexture)
{
// set the proper parameters for an MD2 texture
glGenTextures(1, &thisTexture->texID);
glBindTexture(GL_TEXTURE_2D, thisTexture->texID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
switch (thisTexture->textureType)
{
case BMP:
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, thisTexture->width, thisTexture->height,
GL_RGB, GL_UNSIGNED_BYTE, thisTexture->data);
break;
case PCX:
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, thisTexture->width, thisTexture->height,
GL_RGBA, GL_UNSIGNED_BYTE, thisTexture->data);
case TGA:
break;
default:
break;
}
}
// LoadMD2Model()
// desc: loads an MD2 model specified by filename and with the texture
// specified by textureName
modelData_t *LoadMD2Model(char *filename, char *textureName)
{
FILE *filePtr; // file pointer
int fileLen; // length of model file
char *buffer; // file buffer
modelData_t *model; // the model
modelHeader_t *modelHeader; // model header
texture_t *md2Texture; // model texture
stIndex_t *stPtr; // texture data
frame_t *frame; // frame data
vector_t *pointListPtr; // index variable
mesh_t *triIndex, *bufIndexPtr; // index variables
int i, j; // index variables
// open the model file
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// find length of file
fseek(filePtr, 0, SEEK_END);
fileLen = ftell(filePtr);
fseek(filePtr, 0, SEEK_SET);
// read entire file into buffer
buffer = (char*)malloc(fileLen + 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -