Skip to main content
GameDev.net gamedev.net
🔒 Locked

MD2 Texturing Problem

Started by rpg_code_master Jan 20, 2005 at 4:59 AM 1 replies 500+ views
Original Post
rpg_code_master
rpg_code_master
Hey, My MD2 model isn't texturing properly. You can download the exe and source MD2 problem. Dont mind the memory allocation mess, I can get quite messy when figuring things out ;) My CPP file


// UltraLight_MD2_Load_Save.cpp : Defines the entry point for the DLL application.
//

#include "UltraLight_MD2_Load_Save.h"
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

//===========================================================================================\\

// this is the main method that actaully creates the plugin
extern "C" {
UL_PLUGIN IPlugin* CreatePlugin( void* )
{
	return new CUltraLight_MD2_Load_Save( );
} // end CreatePlugin
}; // end extern "C"

//===========================================================================================\\

/*********************************************************************************************/
//
//	CLASS: CMeshPlugin
//
//	DESC: This is a mesh loader/saver
//
/*********************************************************************************************/

// this returns the plugins ID
// it takes nothing
// it returns the plugins ID
char* CMeshPlugin::GetID( void )
{
	return PLUGID_MESH;
} // end CMeshPlugin::GetID

// this runs the plugin
// it takes the nessercary data
// it retruns the nessercary data
void* CMeshPlugin::Run( void* pData ) 
{
	// do noting... ;)
	return 0;
} // end CMeshPlugin::Run

// this returns a new instance of the plugin if needed
// it takes nothing
// it returns the plugin instance
void* CMeshPlugin::CreateInstance( void )
{
	return new CUltraLight_MD2_Load_Save;
} // end CMeshPlugin::CreateInstance

/*********************************************************************************************/
//
//	CLASS: CUltraLight_MD2_Load_Save
//
//	DESC: This is a md2 model loader/saver
//
/*********************************************************************************************/

// this loads the md2 model file
// it takes the filename of the file to open
// it returns true upon success else returns false
bool CUltraLight_MD2_Load_Save::Load( const char* strFName )
{
	// load in the model
	m_pModel = LoadMD2( (char *const)strFName, "" );
	if ( !m_pModel )
		return false;
	return true;
} // end CUltraLight_MD2_Load_Save::Load

// this loads the md2 model file
// it takes the filename of the file to save
// it returns true upon success else returns false
bool CUltraLight_MD2_Load_Save::Save( const char* strFName )
{
	return true;
} // end CUltraLight_MD2_Load_Save::Save

// this returns the extension of this file format, .md2
// it takes nothing
// it returns the extension of this file format
char* CUltraLight_MD2_Load_Save::GetExt( void )
{
	return "md2";
} // end CUltraLight_MD2_Load_Save::GetExt

// this returns the animation type
eMeshAnimTypes CUltraLight_MD2_Load_Save::GetAnimationType( void )
{
	return eKeyFrame;
} // end CUltraLight_MD2_Load_Save::GetAnimationType

// these return the mesh data
// they take noting
// they return the mesh data
LPVERTEX CUltraLight_MD2_Load_Save::GetVertexs( void )
{
	return m_pModel->m_pVerts;
} // end CUltraLight_MD2_Load_Save::GetVertexs
// this takes the animation to return
LPKEYFRAMEANIMATION CUltraLight_MD2_Load_Save::GetAnimation( int nFrame )
{
	return &m_pModel->m_Anim;
} // end CUltraLight_MD2_Load_Save::GetKeyFrame
int CUltraLight_MD2_Load_Save::GetNumAnimations( void )
{
	return 1;
} // end CUltraLight_MD2_Load_Save::GetNumKeyFrames
unsigned long CUltraLight_MD2_Load_Save::GetNumVertexs( void )
{
	return m_pModel->m_nNumTriangles*3;
} // end CUltraLight_MD2_Load_Save::GetNumVertexs
unsigned short* CUltraLight_MD2_Load_Save::GetVertexIndex( void )
{
	return m_pModel->m_psVertIndex;
} // end CUltraLight_MD2_Load_Save::GetVertexIndex
unsigned long CUltraLight_MD2_Load_Save::GetNumVertexsIndex( void )
{
	return m_pModel->m_nNumTriangles*3;
} // end CUltraLight_MD2_Load_Save::GetNumVertexsIndex
unsigned long CUltraLight_MD2_Load_Save::GetNumTriangles( void )
{
	return m_pModel->m_nNumTriangles;
} // end CUltraLight_MD2_Load_Save::GetNumTriangles

CVector3 CUltraLight_MD2_Load_Save::GetPos( void )
{
	return CVector3( );
} // end CUltraLight_MD2_Load_Save::GetPos
CVector3 CUltraLight_MD2_Load_Save::GetRot( void )
{
	return CVector3( );
} // end CUltraLight_MD2_Load_Save::GetRot
CVector3 CUltraLight_MD2_Load_Save::GetScale( void )
{
	return CVector3( 1,1,1 );
} // end CUltraLight_MD2_Load_Save::GetScale

//===========================================================================================\\

// this loads the md2 model
// it takes the filename of the md2 model to load and the filename(s) of the skins to load
// it returns the loaded model upon success else returns NULL
LPMD2 LoadMD2( char *const strFName, char *const strFTexName )
{
	FILE* fp;
	int nFileLen;
	char *pBuff;

	LPMD2 pModel;
	LPMD2HEADER pModelHeader;
	LPMD2FRAME pFrame;
	LPVERTEX pVecList;
	unsigned short *psVertIndex, *psTexIndex, *psBufIndex, *index;
	LPMD2TEXCOORDINDEX pTexIndex;
	LPMD2TRIANGLE pTri, pTriBuff;

	// open the file
	fp = fopen( strFName, "rb" );
	if ( !fp )
		return NULL;

	// find the length of the file
	fseek( fp, 0, SEEK_END );
	nFileLen = ftell( fp );
	fseek( fp, 0, SEEK_SET );

	// read the entire file into the buffer
	pBuff = (char*)malloc( sizeof( char ) * ( nFileLen + 1 ) );
	if ( !pBuff )
		return NULL;
	fread( pBuff, sizeof( char ), nFileLen, fp );

	// extract the model header
	pModelHeader = (LPMD2HEADER)pBuff;

	// create model memory
	pModel = (LPMD2)malloc( sizeof( MD2 ) );
	if ( !pModel )
		return NULL;

	// create vertex memory
	pModel->m_pVerts = (LPVERTEX)malloc( sizeof( VERTEX ) * pModelHeader->m_nNumTris * 3 * pModelHeader->m_nNumFrames );
	if ( !pModel->m_pVerts )
		return false;

	pTri = (LPMD2TRIANGLE)malloc( sizeof( MD2TRIANGLE ) * pModelHeader->m_nNumTris * pModelHeader->m_nNumFrames );
	if ( !pModel->m_pVerts )
		return false;


	// set member vars.
	pModel->m_nNumPoints = pModelHeader->m_nNumXYZ;
	pModel->m_nNumST     = pModelHeader->m_nNumST;
	pModel->m_nNumFrames = pModelHeader->m_nNumFrames;
	pModel->m_nFrameSize = pModelHeader->m_nFrameSize;

	// setup the animation
	pModel->m_Anim.m_Frames.Init( pModel->m_nNumFrames );
	pModel->m_Anim.m_nNumKeyFrames = pModel->m_nNumFrames;
	pModel->m_Anim.m_nCurrentKeyFrame = 0;
	pModel->m_Anim.m_fIntroperlate = 0.0f;

	// compute all of the models verts
	for ( int n = 0; n < pModel->m_nNumFrames; n++ ) {
		pFrame = (LPMD2FRAME)&pBuff[ pModelHeader->m_nOffsetFrames + pModelHeader->m_nFrameSize * n ];

		// calculate the vert positions based on the frame details
		int nNumXYZ = pModelHeader->m_nNumXYZ;
		pVecList = (LPVERTEX)&pModel->m_pVerts[ pModelHeader->m_nNumXYZ * n ];
		for ( int i = 0; i < nNumXYZ; i++ )
		{
			pVecList[ i ].x = pFrame->m_fScale[ 0 ] * pFrame->m_fp[ i ].v[ 0 ] + pFrame->m_fTranslate[ 0 ];
			pVecList[ i ].y = pFrame->m_fScale[ 1 ] * pFrame->m_fp[ i ].v[ 1 ] + pFrame->m_fTranslate[ 1 ];
			pVecList[ i ].z = pFrame->m_fScale[ 2 ] * pFrame->m_fp[ i ].v[ 2 ] + pFrame->m_fTranslate[ 2 ];
		} // end for
		//pModel->m_Anim.m_Frames[ n ].m_pVerts = pVecList; // set the verts
	} // end for

	// load in the verts
	// create the vert memory
	index = (unsigned short*)malloc( sizeof( unsigned short ) * pModelHeader->m_nNumTris * 3 );

	// set the number of tris
	pModel->m_nNumTriangles = pModelHeader->m_nNumTris;
	pModel->m_psVertIndex = index;

	// point to the tri indecies in the buff
	pTriBuff = (LPMD2TRIANGLE)&pBuff[ pModelHeader->m_nOffsetTris ];

	// point to the texture coords
	pTexIndex = (LPMD2TEXCOORDINDEX)&pBuff[ pModelHeader->m_nOffsetST ];

	// set the mesh
	int nNumTris = pModelHeader->m_nNumTris;

	// calculate the normals and set the texture coords
	for ( int x = 0; x < pModel->m_nNumFrames; x++ ) {
		pVecList = (LPVERTEX)&pModel->m_pVerts[ pModelHeader->m_nNumXYZ * x ];
		pModel->m_Anim.m_Frames[ x ].m_pVerts = new VERTEX[ pModelHeader->m_nNumTris * 3 ];
		pModel->m_Anim.m_Frames[ x ].m_fTime = 0.05f;
		pModel->m_Anim.m_Frames[ x ].m_nNumVerts = pModelHeader->m_nNumTris * 3;

		for ( int i = 0, j = 0, t = 0; i < nNumTris; i++, j += 3 )
		{
			// save the texture coord
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+0 ].x = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 0 ] ].x;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+0 ].y = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 0 ] ].y;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+0 ].z = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 0 ] ].z;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+0 ].u1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 0 ] ].s;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+0 ].v1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 0 ] ].t;

			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+1 ].x = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 1 ] ].x;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+1 ].y = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 1 ] ].y;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+1 ].z = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 1 ] ].z;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+1 ].u1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 1 ] ].s;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+1 ].v1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 1 ] ].t;

			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+2 ].x = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 2 ] ].x;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+2 ].y = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 2 ] ].y;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+2 ].z = pVecList[ pTriBuff[ i ].m_nVertIndicies[ 2 ] ].z;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+2 ].u1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 2 ] ].s;
			pModel->m_Anim.m_Frames[ x ].m_pVerts[ j+2 ].v1 = pTexIndex[ pTriBuff[ i ].m_nTexIndicies[ 2 ] ].t;

			// set the new index buffer
			index[ j+0 ] = j+0;
			index[ j+1 ] = j+1;
			index[ j+2 ] = j+2;



/*
			Tri[ i ].m_nVertIndicies[ 0 ]pVecList[ psVertIndex[ j+0 ] ].u1 = pTexIndex[ psTexIndex[ j+0 ] ].s;
			pVecList[ psVertIndex[ j+0 ] ].v1 = pTexIndex[ psTexIndex[ j+0 ] ].t;

			pVecList[ psVertIndex[ j+1 ] ].u1 = pTexIndex[ psTexIndex[ j+1 ] ].s;
			pVecList[ psVertIndex[ j+1 ] ].v1 = pTexIndex[ psTexIndex[ j+1 ] ].t;

			pVecList[ psVertIndex[ j+2 ] ].u1 = pTexIndex[ psTexIndex[ j+2 ] ].s;
			pVecList[ psVertIndex[ j+2 ] ].v1 = pTexIndex[ psTexIndex[ j+2 ] ].t;
		*/} // end for
		//pModel->m_Anim.m_Frames[ n ].m_pVerts = pVecList; // set the verts
	} // end for

	// finish up
	fclose( fp );
	fflush( fp );
//	free( psTexIndex );
//	free( psVertIndex );
	free( pBuff );

	return pModel;
} // end LoadMD2



My H file


// FILE: UltraLight_MD2_Load_Save.h by Richard Hughes. 10/07/2004
//
// DESC: This defnes all the needed classes etc... to allow the UltraLight(r) game engine to load and save
//       .md2 model files

#ifndef UltraLight_MD2_Load_Save
#define UltraLight_MD2_Load_Save

// INCLUDES
#include "..\\..\\UltraLight\\UltraLight\\MeshPlugin.h"

/*********************************************************************************************/
//
//	STRUCT: tagMD2Vec
//
//	DESC: This is a simple vector to be used with the loading and saving of the md2 model
//
/*********************************************************************************************/

typedef struct tagMD2Vec {
	float x,y,z;
}MD2VEC, *LPMD2VEC;

/*********************************************************************************************/
//
//	STRUCT: tagMD2TexCoordIndex
//
//	DESC: This is a simple tex coord index obj. to be used with the loading and saving of the md2 model
//
/*********************************************************************************************/

typedef struct tagMD2TexCoordIndex {
	unsigned short s,t;
}MD2TEXCOORDINDEX, *LPMD2TEXCOORDINDEX;

/*********************************************************************************************/
//
//	STRUCT: tagMD2FramePoint
//
//	DESC: This is a md2 framepoint
//
/*********************************************************************************************/

typedef struct tagMD2FramePoint {
	unsigned char v[ 3 ];
	unsigned char m_cNormalIndex;
}MD2FRAMEPOINT, *LPMD2FRAMEPOINT;

/*********************************************************************************************/
//
//	STRUCT: tagMD2Frame
//
//	DESC: This is a md2 frame
//
/*********************************************************************************************/

typedef struct tagMD2Frame {
	float m_fScale[ 3 ];
	float m_fTranslate[ 3 ];
	char  m_strName[ 16 ];
	MD2FRAMEPOINT m_fp[ 1 ];
}MD2FRAME, *LPMD2FRAME;

/*********************************************************************************************/
//
//	STRUCT: tagMD2Triangle
//
//	DESC: This is an md2 triangle
//
/*********************************************************************************************/

typedef struct tagMD2Triangle {
	unsigned short m_nVertIndicies[ 3 ];
	unsigned short m_nTexIndicies[ 3 ];
}MD2TRIANGLE, *LPMD2TRIANGLE;

/*********************************************************************************************/
//
//	STRUCT: tagMD2Header
//
//	DESC: This is the md2 model header
//
/*********************************************************************************************/

typedef struct tagMD2Header {
	int m_nIdent;
	int m_nVersion;
	int m_nSkinWidth;
	int m_nSkinHeight;
	int m_nFrameSize;
	int m_nNumSkins;
	int m_nNumXYZ;
	int m_nNumST;
	int m_nNumTris;
	int m_nNumGLCommands;
	int m_nNumFrames;
	int m_nOffsetSkins;
	int m_nOffsetST;
	int m_nOffsetTris;
	int m_nOffsetFrames;
	int m_nOffsetGLCommands;
	int m_nOffsetEnd;
}MD2HEADER, *LPMD2HEADER;

/*********************************************************************************************/
//
//	STRUCT: tagMD2
//
//	DESC: This is the md2 model
//
/*********************************************************************************************/

typedef struct tagMD2 {
	int m_nNumFrames;
	int m_nNumPoints;
	int m_nNumTriangles;
	int m_nNumST;
	int m_nFrameSize;
	int m_nTexWidth, m_nTexHeight;
	int m_nCurrentFrame;
	float m_fInterpole;
	unsigned short *m_psTexIndex;
	unsigned short *m_psVertIndex;
	LPVERTEX m_pVerts;
	KEYFRAMEANIMATION m_Anim;
}MD2, *LPMD2;

// this loads the md2 model
// it takes the filename of the md2 model to load and the filename(s) of the skins to load
// it returns the loaded model upon success else returns NULL
LPMD2 LoadMD2( char *const strFName, char *const strFTexName );

/*********************************************************************************************/
//
//	CLASS: CUltraLight_MD2_Load_Save
//
//	DESC: This is a md2 model loader/saver
//
/*********************************************************************************************/

class CUltraLight_MD2_Load_Save : public CMeshPlugin {

	LPMD2 m_pModel;

public:
	CUltraLight_MD2_Load_Save( void )
	: m_pModel( NULL )
	{
	}
	~CUltraLight_MD2_Load_Save( void )
	{
	}

	// this loads the md2 model file
	bool Load( const char* strFName );

	// this saves the md2 model file
	bool Save( const char* strFName );

	// this returns the extension of this file format, .md2
	char* GetExt( void );

	// this returns the animation type
	eMeshAnimTypes GetAnimationType( void );

	// these return the mesh data
	LPVERTEX GetVertexs( void );
	LPKEYFRAMEANIMATION GetAnimation( int nFrame );
	int GetNumAnimations( void );
	unsigned long GetNumVertexs( void );
	unsigned short* GetVertexIndex( void );
	unsigned long GetNumVertexsIndex( void );
	unsigned long GetNumTriangles( void );

	CVector3 GetPos( void );
	CVector3 GetRot( void );
	CVector3 GetScale( void );

	QUICK_SIZE;
}; // end class CUltraLight_MD2_Load_Save

#endif /* UltraLight_MD2_Load_Save */

// EOF: UltraLight_MD2_Load_Save.h



[Edited by - rpg_code_master on January 20, 2005 5:19:04 AM]
noisecrime
noisecrime
hi,

I think you've got two problems.

Firstly try defining your texture coordinates s,t as shorts,not unsigned shorts, i'm not certain about this, and have meant to test it at some point, but its not unfeasable for negative texture coordiantes i guess.

Then for loading in your coords you need to divide each by the respective length of the texture dimensions.

new_S = (float)m_pTexCoords.s/m_Header.skinWidth
new_T = (float)m_pTexCoords.t/m_Header.skinHieght
or
new_T = 1.0-(float)m_pTexCoords.t/m_Header.skinHieght
if the texture is flipped vertically.
rpg_code_master
rpg_code_master
Yer, i'm sure that i've divided the tex coords by the widths in the engine. are there any other posible problems?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.