📄 model.cpp
字号:
#include "model.h"#include <cassert>
#include <algorithm>#include "util.h"int globalTime = 0;//int globalFrame = 0;AnimManager::AnimManager(ModelAnimation *anim) {
anims = anim;
AnimateParticles = false;
Count = 1;
PlayIndex = 0;
CurLoop = 0;
animList[0].AnimID = 0;
animList[0].Loops = 0;
if (anims != NULL) {
Frame = anims[0].timeStart;
TotalFrames = anims[0].timeEnd - anims[0].timeStart;
} else {
Frame = 0;
TotalFrames = 0;
}
Paused = false;
}AnimManager::~AnimManager() { anims = NULL;}void AnimManager::AddAnim(short id, short loops) {
if (Count > 3)
return;
animList[Count].AnimID = id;
animList[Count].Loops = loops;
Count++;
}void AnimManager::Set(short index, short id, short loops) {
// error check, we currently only support 4 animations.
if (index > 3)
return;
animList[index].AnimID = id;
animList[index].Loops = loops;
// Just an error check for our "auto animate"
if (index == 0) {
if (Count == 0)
Count = 1;
PlayIndex = index;
Frame = anims[id].timeStart;
TotalFrames = anims[id].timeEnd - anims[id].timeStart;
}
}void AnimManager::Play() {
PlayIndex = 0;
//if (Frame == 0 && PlayID == 0) {
CurLoop = animList[PlayIndex].Loops;
Frame = anims[animList[PlayIndex].AnimID].timeStart;
TotalFrames = anims[animList[PlayIndex].AnimID].timeEnd - anims[animList[PlayIndex].AnimID].timeStart;
//}
Paused = false;
AnimateParticles = false;
}void AnimManager::Stop() {
Paused = true;
PlayIndex = 0;
Frame = anims[animList[0].AnimID].timeStart;
CurLoop = animList[0].Loops;
}void AnimManager::Pause(bool force) {
if (Paused && force == false) {
Paused = false;
AnimateParticles = !Paused;
} else {
Paused = true;
AnimateParticles = !Paused;
}
}void AnimManager::Next() {
if(CurLoop == 1) {
PlayIndex++;
if (PlayIndex >= Count) {
Stop();
return;
}
CurLoop = animList[PlayIndex].Loops;
} else if(CurLoop > 1) {
CurLoop--;
}
Frame = anims[animList[PlayIndex].AnimID].timeStart;
}void AnimManager::Prev() {
if(CurLoop >= animList[PlayIndex].Loops) {
PlayIndex--;
if (PlayIndex < 0) {
Stop();
return;
}
CurLoop = animList[PlayIndex].Loops;
} else if(CurLoop < animList[PlayIndex].Loops) {
CurLoop++;
}
Frame = anims[animList[PlayIndex].AnimID].timeEnd;
}int AnimManager::Tick(int time) {
if((Count < PlayIndex) )
return -1;
Frame += time;
if (Frame >= anims[animList[PlayIndex].AnimID].timeEnd) {
Next();
return 1;
} else if (Frame < anims[animList[PlayIndex].AnimID].timeStart) {
Prev();
return 1;
}
return 0;
}unsigned int AnimManager::GetFrameCount() {
return (anims[animList[PlayIndex].AnimID].timeEnd - anims[animList[PlayIndex].AnimID].timeStart);
}
void AnimManager::NextFrame(){ //AnimateParticles(); int id = animList[PlayIndex].AnimID; Frame += int((anims[id].timeEnd - anims[id].timeStart) / 60); TimeDiff = int((anims[id].timeEnd - anims[id].timeStart) / 60);}void AnimManager::PrevFrame()
{
//AnimateParticles();
int id = animList[PlayIndex].AnimID;
Frame -= int((anims[id].timeEnd - anims[id].timeStart) / 60);
TimeDiff = int((anims[id].timeEnd - anims[id].timeStart) / 60) * -1;
}
void AnimManager::SetFrame(unsigned int f){ //TimeDiff = f - Frame; Frame = f;}int AnimManager::GetTimeDiff(){ int t = TimeDiff; TimeDiff = 0; return t;}void AnimManager::SetTimeDiff(int i){ TimeDiff = i;}void AnimManager::Clear() {
Stop();
Paused = true;
PlayIndex = 0;
Count = 0;
CurLoop = 0;
Frame = 0;
}Model::Model(std::string name, bool forceAnim) : ManagedItem(name), forceAnim(forceAnim){ if (name == "") return; // replace .MDX with .M2 char tempname[256]; strcpy(tempname, name.c_str()); if (tempname[name.length()-1] != '2') { tempname[name.length()-2] = '2'; tempname[name.length()-1] = 0; } // Initiate our model variables. trans = 1.0f; rad = 1.0f; for (int i=0; i<32; i++) { specialTextures[i] = -1; replaceTextures[i] = 0; useReplaceTextures[i] = false; } for (int i=0; i<40; i++) attLookup[i] = -1; bounds = 0; boundTris = 0; showGeosets = 0; hasCamera = false; hasParticles = false; isWMO = false; isMounted = false;
vbuf = nbuf = tbuf = 0;
origVertices = 0;
vertices = 0;
normals = 0;
texcoords = 0;
indices = 0;
animtime = 0; anim = 0; anims = 0; animManager = 0; bones = 0; bounds = 0; boundTris = 0; currentAnim = 0; colors = 0; globalSequences = 0; lights = 0; particleSystems = 0; ribbons = 0; texanims = 0; textures = 0; transparency = 0; // -- MPQFile f(tempname); ok = !f.isEof(); if (!ok || (f.getSize() < sizeof(ModelHeader))) { wxLogMessage("Error loading model [%s]\n", tempname); // delete this; //? return; } memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); animated = isAnimated(f) || forceAnim; // isAnimated will set animGeometry and animTextures wxLogMessage("Loading model %s%s\n", tempname, animated ? " (animated)" : ""); if (header.nGlobalSequences) { globalSequences = new int[header.nGlobalSequences]; memcpy(globalSequences, (f.getBuffer() + header.ofsGlobalSequences), header.nGlobalSequences * 4); } if (forceAnim) animBones = true; if (animated) initAnimated(f); else initStatic(f); f.close();}Model::~Model(){ if (ok) { wxLogMessage("Unloading model %s\n", name.c_str()); if (header.nTextures) { for (size_t i=0; i<header.nTextures; i++) { if (textures[i]!=0) { texturemanager.del(textures[i]); } } delete[] textures; /* for (int i=0; i<32; i++) { if (replaceTextures[i]!=0) texturemanager.del(replaceTextures[i]); } */ } delete[] globalSequences; if (bounds) delete[] bounds; if (boundTris) delete[] boundTris; if (showGeosets) delete[] showGeosets; if (animated) { // unload all sorts of crap // Need this if statement because VBO supported
// cards have already deleted it.
if(!supportVBO) {
if(!animGeometry)
delete[] normals;
delete[] vertices;
delete[] texcoords;
}
delete[] indices;
delete[] anims; delete[] origVertices; if (animManager) delete animManager; if (animBones) delete[] bones; if (supportVBO) {
if (!animGeometry) { glDeleteBuffersARB(1, &nbuf); } glDeleteBuffersARB(1, &vbuf); glDeleteBuffersARB(1, &tbuf); }
if (animTextures) delete[] texanims; if (colors) delete[] colors; if (transparency) delete[] transparency; if (lights) delete[] lights; if (particleSystems) delete[] particleSystems; if (ribbons) delete[] ribbons; } else { glDeleteLists(dlist, 1); } }}bool Model::isAnimated(MPQFile &f)
{
// see if we have any animated bones
ModelBoneDef *bo = (ModelBoneDef*)(f.getBuffer() + header.ofsBones);
animGeometry = false;
animBones = false;
ind = false;
ModelVertex *verts = (ModelVertex*)(f.getBuffer() + header.ofsVertices);
for (size_t i=0; i<header.nVertices && !animGeometry; i++) {
for (size_t b=0; b<4; b++) {
if (verts[i].weights[b]>0) {
ModelBoneDef &bb = bo[verts[i].bones[b]];
if (bb.translation.type || bb.rotation.type || bb.scaling.type || (bb.flags&8)) {
if (bb.flags&8) {
// if we have billboarding, the model will need per-instance animation
ind = true;
}
animGeometry = true;
break;
}
}
}
}
if (animGeometry) animBones = true;
else {
for (size_t i=0; i<header.nBones; i++) {
ModelBoneDef &bb = bo[i];
if (bb.translation.type || bb.rotation.type || bb.scaling.type) {
animBones = true;
break;
}
}
}
animTextures = header.nTexAnims > 0;
bool animMisc = header.nCameras>0 || // why waste time, pretty much all models with cameras need animation
header.nLights>0 || // same here
header.nParticleEmitters>0 ||
header.nRibbonEmitters>0;
if (animMisc) animBones = true;
// animated colors
if (header.nColors) {
ModelColorDef *cols = (ModelColorDef*)(f.getBuffer() + header.ofsColors);
for (size_t i=0; i<header.nColors; i++) {
if (cols[i].color.type!=0 || cols[i].opacity.type!=0) {
animMisc = true;
break;
}
}
}
// animated opacity
if (header.nTransparency && !animMisc) {
ModelTransDef *trs = (ModelTransDef*)(f.getBuffer() + header.ofsTransparency);
for (size_t i=0; i<header.nTransparency; i++) {
if (trs[i].trans.type!=0) {
animMisc = true;
break;
}
}
}
// guess not...
return animGeometry || animTextures || animMisc;
}
Vec3D fixCoordSystem(Vec3D v){ return Vec3D(v.x, v.z, -v.y);}Vec3D fixCoordSystem2(Vec3D v){ return Vec3D(v.x, v.z, v.y);}Quaternion fixCoordSystemQuat(Quaternion v){ return Quaternion(-v.x, -v.z, v.y, v.w);}void Model::initCommon(MPQFile &f){ // assume: origVertices already set if (!animGeometry || !supportVBO) { vertices = new Vec3D[header.nVertices]; normals = new Vec3D[header.nVertices]; } // vertices, normals for (size_t i=0; i<header.nVertices; i++) { origVertices[i].pos = fixCoordSystem(origVertices[i].pos); origVertices[i].normal = fixCoordSystem(origVertices[i].normal); if (!animGeometry || !supportVBO) { vertices[i] = origVertices[i].pos; normals[i] = origVertices[i].normal.normalize(); } float len = origVertices[i].pos.lengthSquared();
if (len > rad){
rad = len;
} } rad = sqrtf(rad); // bounds if (header.nBoundingVertices > 0) { bounds = new Vec3D[header.nBoundingVertices]; Vec3D *b = (Vec3D*)(f.getBuffer() + header.ofsBoundingVertices); for (size_t i=0; i<header.nBoundingVertices; i++) { bounds[i] = fixCoordSystem(b[i]); } } if (header.nBoundingTriangles > 0) { boundTris = new uint16[header.nBoundingTriangles]; memcpy(boundTris, f.getBuffer() + header.ofsBoundingTriangles, header.nBoundingTriangles*sizeof(uint16)); } // textures ModelTextureDef *texdef = (ModelTextureDef*)(f.getBuffer() + header.ofsTextures); if (header.nTextures) { textures = new TextureID[header.nTextures]; for (size_t i=0; i<header.nTextures; i++) { char texname[256]; if (texdef[i].type == 0) { strncpy(texname, (const char*)f.getBuffer() + texdef[i].nameOfs, texdef[i].nameLen); texname[texdef[i].nameLen] = 0; std::string path(texname); //fixname(path);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -