📄 gmd.cpp
字号:
#include <iostream>
#include <fstream>
#include "gmdformat.h"
#include "gmd.h"
#include "../math/vector.h"
#include "../math/math.h"
using namespace std;
///////////////////////////////////////////////////////////////////////////////////////////
GcGMD::GcGMD():
triangles(NULL),
vertices(NULL),
texCoords(NULL),
texture(NULL),
interpol(0.0f),
activeSkin(0)
{
}
///////////////////////////////////////////////////////////////////////////////////////////
GcGMD::~GcGMD()
{
// Destroy the model
Destroy();
}
///////////////////////////////////////////////////////////////////////////////////////////
bool GcGMD::Load(char *fileName, char *skinName)
{
// Load the model
Load(fileName);
// Allocate memory for the skin
texture = new GcTexture[1];
// Create the texture
texture[0].Create(skinName);
// Set the active skin
activeSkin = 0;
header.numSkins = 1;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
bool GcGMD::Load(char *fileName)
{
// Open the file for reading
ifstream file(fileName, ios::in | ios::binary);
// Check for success
if(!file) {
return false;
}
// Read the head from the file
file.read((char*)&header, sizeof(GMDHeader));
// Allocate memory from the vertices
vertices = new GcPoint3[header.numVertices * header.numFrames];
// Read the vertices from the file
file.read((char*)vertices, sizeof(GcPoint3) * header.numVertices * header.numFrames);
// Allocate memory for the texture coordinates
texCoords = new GcPoint2[header.numTexCoords];
// Read the texture coordinates from the file
file.read((char*)texCoords, sizeof(GcPoint2) * header.numTexCoords);
// Allocate memory for the triangles
triangles = new GMDTri[header.numTris];
// Find the correct reading position
file.seekg(header.offsetTris, ios::beg);
// Read the triangles from the file
file.read((char*)triangles, sizeof(GMDTri) * header.numTris);
// No skin was loaded
header.numSkins = 0;
/* Find the extreme points for the bounding box */
GcVector3 extreme(0, 0, 0);
GcPoint3 currPoint;
for(int i = 0; i < header.numTris; i++)
{
// Get the first points from this fram and the next
currPoint.x = vertices[triangles[i].triInd[0]].x;
currPoint.y = vertices[triangles[i].triInd[0]].y;
currPoint.z = vertices[triangles[i].triInd[0]].z;
if(currPoint.x > extreme.x) {
extreme.x = currPoint.x;
}
if(currPoint.y > extreme.y) {
extreme.y = currPoint.y;
}
if(currPoint.z > extreme.z) {
extreme.z = currPoint.z;
}
}
g_Debug->Log("Extreme x: %f - y: %f - z: %f\n", extreme.x, extreme.y, extreme.z );
SetExtents(extreme);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
bool GcGMD::LoadSkin(char *skinName, uint index)
{
// Check to see that the skin is valid and that a texture space for it exist
if((texture == NULL) || (index > header.numSkins - 1)) {
g_Debug->Log("Failed to load skin %d\n", index);
return false;
}
// Create the skin
texture[index].Create(skinName);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
void GcGMD::SetNumberOfSkins(uint num)
{
// Delete previus textures if needed
if(texture != NULL) {
delete [] texture;
}
// Create new textures
texture = new GcTexture[num];
// Save the number of skins
header.numSkins = num;
}
///////////////////////////////////////////////////////////////////////////////////////////
bool GcGMD::Animate(int startFrame, int endFrame, float percent)
{
GcPoint3 *currList; // Holds the current frame's vertices
GcPoint3 *nextList; // Holds the next frame's vertices
GcPoint3 currPoint;
GcPoint3 nextPoint;
GcPoint3 vertex[3]; // The vertex's to be rendered
GcVector3 normal; // The vertex normal
if(startFrame > currentFrame) {
currentFrame = startFrame;
}
if((startFrame < 0) || (endFrame < 0)) {
return false;
}
if((startFrame >= header.numFrames) || (endFrame >= header.numFrames)) {
return false;
}
if(interpol >= 1.0f)
{
// Re-set the interpolation
interpol = 0.0f;
// Another fram has gone by
currentFrame++;
// Time to start the animation over?
if(currentFrame >= endFrame) {
currentFrame = startFrame;
}
// Set the next frame
nextFrame = currentFrame + 1;
// Time to start the animation over?
if(nextFrame >= endFrame) {
nextFrame = startFrame;
}
}
// Set the pointers to point to this frame's vertices, and the next
currList = &vertices[header.numVertices * currentFrame];
nextList = &vertices[header.numVertices * nextFrame];
// Bind the texture for the model
if(header.numSkins > 0) {
texture[activeSkin].Bind();
}
glPushMatrix();
glMultMatrixf(m_worldMatrix);
glBegin(GL_TRIANGLES);
for(int i = 0; i < header.numTris; i++)
{
// Get the first points from this fram and the next
currPoint.x = currList[triangles[i].triInd[0]].x;
currPoint.y = currList[triangles[i].triInd[0]].y;
currPoint.z = currList[triangles[i].triInd[0]].z;
nextPoint.x = nextList[triangles[i].triInd[0]].x;
nextPoint.y = nextList[triangles[i].triInd[0]].y;
nextPoint.z = nextList[triangles[i].triInd[0]].z;
// Claculate the first interpolated vertex
vertex[0] = (nextPoint - currPoint) * interpol + currPoint;
// Get the first points from this fram and the next
currPoint.x = currList[triangles[i].triInd[1]].x;
currPoint.y = currList[triangles[i].triInd[1]].y;
currPoint.z = currList[triangles[i].triInd[1]].z;
nextPoint.x = nextList[triangles[i].triInd[1]].x;
nextPoint.y = nextList[triangles[i].triInd[1]].y;
nextPoint.z = nextList[triangles[i].triInd[1]].z;
// Claculate the second interpolated vertex
vertex[1] = (nextPoint - currPoint) * interpol + currPoint;
// Get the first points from this fram and the next
currPoint.x = currList[triangles[i].triInd[2]].x;
currPoint.y = currList[triangles[i].triInd[2]].y;
currPoint.z = currList[triangles[i].triInd[2]].z;
nextPoint.x = nextList[triangles[i].triInd[2]].x;
nextPoint.y = nextList[triangles[i].triInd[2]].y;
nextPoint.z = nextList[triangles[i].triInd[2]].z;
// Claculate the first interpolated vertex
vertex[2] = (nextPoint - currPoint) * interpol + currPoint;
// Calculate the normal
normal = GcMath::ClaculateNormal(vertex[0], vertex[1], vertex[3]);
// Give the normal to OpenGL
glNormal3f(normal.x, normal.y, normal.z);
// Render the triangle
glTexCoord2f(texCoords[triangles[i].texCrdInd[0]].x,
texCoords[triangles[i].texCrdInd[0]].y);
glVertex3fv(vertex[0].array);
glTexCoord2f(texCoords[triangles[i].texCrdInd[2]].x,
texCoords[triangles[i].texCrdInd[2]].y);
glVertex3fv(vertex[2].array);
glTexCoord2f(texCoords[triangles[i].texCrdInd[1]].x,
texCoords[triangles[i].texCrdInd[1]].y);
glVertex3fv(vertex[1].array);
}
glEnd();
glPopMatrix();
interpol += percent;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
bool GcGMD::RenderKeyFrame(int frame)
{
GcPoint3 *currList; // Holds the current frame's vertices
GcPoint3 vertex[3]; // The vertices to be rendered
GcVector3 normal; // The triangle normal
// Check for a valid frame
if(frame < 0 || frame > header.numFrames) {
return false;
}
// Set the pointers to point to this frame's vertices
currList = &vertices[header.numVertices * frame];
// Bind the texture for the model
if(header.numSkins > 0) {
texture[activeSkin].Bind();
}
glPushMatrix();
glMultMatrixf(m_worldMatrix);
glBegin(GL_TRIANGLES);
for(int i = 0; i < header.numTris; i++)
{
// Get the first point from this frame
vertex[0].x = currList[triangles[i].triInd[0]].x;
vertex[0].y = currList[triangles[i].triInd[0]].y;
vertex[0].z = currList[triangles[i].triInd[0]].z;
// Get the second point from this frame
vertex[1].x = currList[triangles[i].triInd[1]].x;
vertex[1].y = currList[triangles[i].triInd[1]].y;
vertex[1].z = currList[triangles[i].triInd[1]].z;
// Get the third point from this frame
vertex[2].x = currList[triangles[i].triInd[2]].x;
vertex[2].y = currList[triangles[i].triInd[2]].y;
vertex[2].z = currList[triangles[i].triInd[2]].z;
// Calculate the normal
normal = GcMath::ClaculateNormal(vertex[0], vertex[1], vertex[3]);
// Give the normal to OpenGL
glNormal3f(normal.x, normal.y, normal.z);
// Render the triangle
glTexCoord2f(texCoords[triangles[i].texCrdInd[0]].x,
texCoords[triangles[i].texCrdInd[0]].y);
glVertex3fv(vertex[0].array);
glTexCoord2f(texCoords[triangles[i].texCrdInd[2]].x,
texCoords[triangles[i].texCrdInd[2]].y);
glVertex3fv(vertex[2].array);
glTexCoord2f(texCoords[triangles[i].texCrdInd[1]].x,
texCoords[triangles[i].texCrdInd[1]].y);
glVertex3fv(vertex[1].array);
}
glEnd();
glPopMatrix();
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
void GcGMD::Destroy()
{
// Clean up the memory
if(triangles != NULL) {
delete [] triangles;
triangles = NULL;
}
if(vertices != NULL) {
delete [] vertices;
vertices = NULL;
}
if(texCoords != NULL) {
delete [] texCoords;
texCoords = NULL;
}
if(texture != NULL) {
delete [] texture;
texture = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -