📄 mdx.cpp
字号:
/********************************************************************************
Warcraft 3 Viewer - Utility to view models and textures from Warcraft 3
Copyright (C) 2002 David GRIMBICHLER (theprophet@wanadoo.Fr)
http://www.xeberon.net
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
********************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <time.h>
#include <io.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <d3dx9.h>
#include "math.h"
#include "mdx.h"
#include "blp.h"
#ifndef PI
#define PI 3.1415926535897932385f
#endif
extern DWORD FromMPQ(char*filename, char*& buffer);
extern BOOL g_showmeshes[MAX_CHUNKS];
extern MaChaine gLoadedTextures[128];
extern Vec3 MColor;
extern long bCam;
extern BOOL bShowCameras;
extern WarCraft_BLP gTex;
WarCraft_ModelX* singleton = NULL;
extern void *malloc_func(const size_t size);
extern void free_func(void* ptr);
WarCraft_ModelX::WarCraft_ModelX(void) :
mpData(NULL),
mSize(0),
mLoaded(false)
{
singleton = this;
}
void WarCraft_ModelX::Free(void)
{
if(mTextures.mNumTextures)
glDeleteTextures(mTextures.mNumTextures,(GLuint*)mTextures.mGLBind);
if(mpData.c!=NULL)
free_func(mpData.c);
ZeroMemory(this,sizeof(WarCraft_ModelX));
}
WarCraft_ModelX::~WarCraft_ModelX(void)
{
Free();
singleton = NULL;
}
void WarCraft_ModelX::Render(void)
{
if(false == mLoaded)
return;
mGeometry.Render();
if((bCam < 0)&&(bShowCameras == TRUE)) mCameras.Render();
}
void WarCraft_ModelX::Load(char* inName)
{
if(gTex.glbind)
glDeleteTextures(1,&gTex.glbind);
gTex.glbind = 0;
ZeroMemory(&gLoadedTextures, sizeof(gLoadedTextures));
toregistre("Attempting to read file %s...",inName);
mSize = FromMPQ(inName,mpData.c);
if(!mSize)
return;
//////////////////////////////////////////////////////////
// File processing part
TypePointer1 p(mpData.p);
//
// First check the tag
//
if('MDLX' != TAG(*p.dw))
{
toregistre("Missing model tag : '%c%c%c%c' instead of 'MDLX'",p.c[0],p.c[1],p.c[2],p.c[3]);
return;
}
p.dw++;
//
// Main processing loop
// parse all sections
//
while(p.c < mpData.c+mSize)
{
switch(TAG(*p.dw))
{
case 'BONE':
{
p.dw++;
int size = *p.dw++;
p.c += size;
}
break;
case 'VERS': // VERSion
{
p.dw++;
int size = *p.dw++;
mVersion.Read(p,size);
if( !mVersion.IsValid() )
return;
// mVersion.Print();
p.c += size;
}
break;
case 'MODL': // MODeL
{
p.dw++;
int size = *p.dw++;
mModel.Read(p,size);
// mModel.Print();
p.c += size;
}
break;
case 'GEOS': // GEOmetry Section or whatever....
{
p.dw++;
int size = *p.dw++;
mGeometry.Read(p,size);
// mGeometry.Print();
p.c += size;
}
break;
case 'SEQS': // SEQuences
{
p.dw++;
int size = *p.dw++;
mSequences.Read(p,size);
// mSequences.Print();
p.c += size;
}
break;
case 'TEXS': // TEXtureS
{
p.dw++;
int size = *p.dw++;
mTextures.Read(p,size);
mTextures.Print();
p.c += size;
}
break;
case 'MTLS': // MaTeriaLS
{
p.dw++;
int size = *p.dw++;
mMaterials.Read(p,size);
mMaterials.Print();
p.c += size;
}
break;
case 'CAMS': // Cameras
{
p.dw++;
int size = *p.dw++;
mCameras.Read(p, size);
p.c += size;
}
break;
default:
{
toregistre("Unknown tag found : '%c%c%c%c'",p.c[0],p.c[1],p.c[2],p.c[3]);
p.dw++;
int size = *p.dw++;
p.c += size;
}
break;
}
}
//////////////////////////////////////////////////////////
mLoaded = true;
}
void mdxGeoChunk::Read(TypePointer1 inP,int inSize)
{
TypePointer1 p(inP);
int n = 0;
while((p.c < inP.c+inSize) && (n<8))
{
switch(TAG(*p.dw))
{
case 'VRTX': // vertex
{
p.dw++;
mNumVertices = *p.dw++;
mVertices = p.v3;
p.c += mNumVertices*12;
++n;
}
break;
case 'NRMS': // normal
{
p.dw++;
int NumNormals = *p.dw++;
if(mNumVertices != NumNormals)
{
toregistre("NumVertices and NumNormals does not match !!!!!!!!!");
}
mNormals = p.v3;
p.c += NumNormals*12;
++n;
}
break;
case 'PTYP': // primitives type
{
p.dw++;
int size = *p.dw++;
if(*p.dw != 4) // == Triangles
{
toregistre("Unknown polytype !!!!!!!!!!!");
return;
}
p.c += size*4;
++n;
}
break;
case 'PCNT': // primitives count
{
p.dw++;
int size = *p.dw++;
mPolyCount = (*p.dw)/3;
p.c += size*4;
++n;
}
break;
case 'PVTX': // primitives vertices
{
p.dw++;
int size = *p.dw++;
mTriangles = p.tri;
if(size/3 != mPolyCount)
{
toregistre("Polycount and size of triangle block do not match!!!!!!!!!!!");
return;
}
p.c += size*2;
++n;
}
break;
case 'GNDX': // vertex group indices
// links every vertex to a matrix
{
p.dw++;
int size = *p.dw++;
if(mNumVertices != size)
{
toregistre("NumVertices and vertex group index count do not match !!!!!!!!!");
}
mVertexGroupIndices = p.c;
p.c += size;
++n;
}
break;
case 'MTGC': // group matrix counts
// this is the number of vertices defined by GNDX for each matrix
{
p.dw++;
int size = *p.dw++;
p.c += size*4;
++n;
}
break;
case 'MATS': // matrices
{
p.dw++;
int size = *p.dw++;
p.c += size*4;
++n;
}
break;
default:
{
//__asm int 3;
toregistre("Unknown geotag found : '%c%c%c%c'",p.c[0],p.c[1],p.c[2],p.c[3]);
p.dw++;
int size = *p.dw++;
p.c += size;
}
break;
}
}
//
// Now process the remaining data :
//
if(p.c < inP.c+inSize)
{
mMaterial = *p.dw++;
mUnk2 = *p.dw++;
mUnk3 = *p.dw++;
mUnk4 = *p.f++;
mMins = p.v3++;
mMaxs = p.v3++;
mSomeCount = *p.dw++;
for(int i=0;i<mSomeCount;++i)
{
p.f++; // some float
p.v3++; // vec3
p.v3++; // vec3
// combinations....
}
if(TAG(*p.dw) == 'UVAS' )
{
p.dw++;
int size = *p.dw++; // no skip
if(TAG(*p.dw) == 'UVBS' )
{
p.dw++;
int size = *p.dw++;
mUVs = p.v2;
p.c += size*8;
}
else
toregistre("UVBS geotag missing, instead: '%c%c%c%c'",p.c[0],p.c[1],p.c[2],p.c[3]);
}
else
toregistre("Unknown geotag found : '%c%c%c%c'",p.c[0],p.c[1],p.c[2],p.c[3]);
}
else
toregistre("No data remainder in geoset...");
}
void mdxModel::RenderBBox(void)
{
if(!mMins || !mMaxs)
return;
glDisable(GL_LIGHTING);
Vec3 mins = *mMins;
Vec3 maxs = *mMaxs;
glColor3f(0.3f,0.9f,0.3f);
glBegin(GL_LINE_LOOP);
glVertex3fv(mins);
glVertex3f(mins[0],maxs[1],mins[2]);
glVertex3f(maxs[0],maxs[1],mins[2]);
glVertex3f(maxs[0],mins[1],mins[2]);
glVertex3f(maxs[0],mins[1],maxs[2]);
glVertex3fv(maxs);
glVertex3f(mins[0],maxs[1],maxs[2]);
glVertex3f(mins[0],mins[1],maxs[2]);
glVertex3fv(mins);
glEnd();
glBegin(GL_LINES);
glVertex3fv(mins);
glVertex3f(maxs[0],mins[1],mins[2]);
glVertex3f(mins[0],mins[1],maxs[2]);
glVertex3f(maxs[0],mins[1],maxs[2]);
glVertex3fv(maxs);
glVertex3f(maxs[0],maxs[1],mins[2]);
glVertex3f(mins[0],maxs[1],maxs[2]);
glVertex3f(mins[0],maxs[1],mins[2]);
glEnd();
glEnable(GL_LIGHTING);
}
void mdxGeometry::Read(TypePointer1 inP,int inSize)
{
if(mLoaded)
{
toregistre("Duplicate GEOS tag... ignoring");
return;
}
mLoaded = true;
TypePointer1 p(inP);
//
// read the chunks
//
while(p.c<inP.c+inSize)
{
int size = (*p.dw++)-4;
mChunks[mNumChunks].Read(p,size);
p.c += size;
++mNumChunks;
}
}
void mdxGeometry::Render(void)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glDepthFunc(GL_LEQUAL);
glColor3f(1,1,1);
for(int i=0;i<mNumChunks;++i)
{
if(g_showmeshes[i] == TRUE) mChunks[i].Render();
}
}
void mdxGeometry::Print(void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -