Bonjour,

Quelqu'un peut il m'aider à charger un modèle de type MD2, j'ai lu le tutoriel mais je suis trop con pour le comprendre, quand je veux mettre la texture sur mon modèle au lieu d'avoir la texture bien mise sur mon modèle j'ai une sorte de couleur uniforme qui le recouvre entièrement.

En plus je ne peux pas faire des tests sur la source qu'ils donnent car il ne se compile pas (plein d'erreur)

Je pense que ça vient plutôt du loader MD2 que de mon loader de TGA car si je fait moi même un carré et que j'y met une texture c'est parfait.

Ca doit bugger sur : glTexCoord2f( s, t ); mais a priori j'ai fait un copier-coller du code qu'il donne je vois pas pourquoi cela ne fonctionne pas.

Loader de TGA que j'utilise :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 
 
#include <windows.h>
#include <stdio.h>
 
#include <gl/gl.h>
#include <gl/glu.h>
 
#include "TGA.h"
 
TGA::TGA()
{
	this->imageData = NULL;									// Image Data (Up To 32 Bits)
	this->bpp = 0;											// Image Color Depth In Bits Per Pixel
	this->width = 0;											// Image Width
	this->height = 0;											// Image Height
	this->texID = 0;	
}
 
TGA::~TGA()
{
 
}
 
bool TGA::LoadTGA(char *filename)			// Loads A TGA File Into Memory
{    
	GLubyte		TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};	// Uncompressed TGA Header
	GLubyte		TGAcompare[12];								// Used To Compare TGA Header
	GLubyte		header[6];									// First 6 Useful Bytes From The Header
	GLuint		bytesPerPixel;								// Holds Number Of Bytes Per Pixel Used In The TGA File
	GLuint		imageSize;									// Used To Store The Image Size When Setting Aside Ram
	GLuint		temp;										// Temporary Variable
	GLuint		type=GL_RGBA;								// Set The Default GL Mode To RBGA (32 BPP)
 
	FILE *file = fopen(filename, "rb");						// Open The TGA File
 
	if(	file==NULL ||										// Does File Even Exist?
		fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||	// Are There 12 Bytes To Read?
		memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0				||	// Does The Header Match What We Want?
		fread(header,1,sizeof(header),file)!=sizeof(header))				// If So Read Next 6 Header Bytes
	{
		if (file == NULL)									// Did The File Even Exist? *Added Jim Strong*
			return false;									// Return False
		else
		{
			fclose(file);									// If Anything Failed, Close The File
			return false;									// Return False
		}
	}
 
	this->width  = header[1] * 256 + header[0];			// Determine The TGA Width	(highbyte*256+lowbyte)
	this->height = header[3] * 256 + header[2];			// Determine The TGA Height	(highbyte*256+lowbyte)
 
 	if(	this->width	<=0	||								// Is The Width Less Than Or Equal To Zero
		this->height	<=0	||								// Is The Height Less Than Or Equal To Zero
		(header[4]!=24 && header[4]!=32))					// Is The TGA 24 or 32 Bit?
	{
		fclose(file);										// If Anything Failed, Close The File
		return false;										// Return False
	}
 
	this->bpp	= header[4];							// Grab The TGA's Bits Per Pixel (24 or 32)
	bytesPerPixel	= this->bpp/8;						// Divide By 8 To Get The Bytes Per Pixel
	imageSize		= this->width*this->height*bytesPerPixel;	// Calculate The Memory Required For The TGA Data
 
	this->imageData=(GLubyte *)malloc(imageSize);		// Reserve Memory To Hold The TGA Data
 
	if(	this->imageData==NULL ||							// Does The Storage Memory Exist?
		fread(this->imageData, 1, imageSize, file)!=imageSize)	// Does The Image Size Match The Memory Reserved?
	{
		if(this->imageData!=NULL)						// Was Image Data Loaded
			free(this->imageData);						// If So, Release The Image Data
 
		fclose(file);										// Close The File
		return false;										// Return False
	}
 
	for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)		// Loop Through The Image Data
	{														// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
		temp=this->imageData[i];							// Temporarily Store The Value At Image Data 'i'
		this->imageData[i] = this->imageData[i + 2];	// Set The 1st Byte To The Value Of The 3rd Byte
		this->imageData[i + 2] = temp;					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
	}
 
	fclose (file);											// Close The File
 
	// Build A Texture From The Data
	glGenTextures(1, &(this->texID));					// Generate OpenGL texture IDs
	glBindTexture(GL_TEXTURE_2D, this->texID);			// Bind Our Texture
 
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
	if (this->bpp==24){type=GL_RGB;}
	glTexImage2D(GL_TEXTURE_2D, 0, type, this->width, this->height, 0, type, GL_UNSIGNED_BYTE, this->imageData);
 
	return true;										
}
et voici le loader de MD2 que j'ai :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
 
 
#include	"MD2.h"
 
#include <windows.h>		// Header File For Windows
#include <gl\gl.h>			// Header File For The OpenGL32 Library
#include <gl\glu.h>			// Header File For The GLu32 Library
 
#include <fstream>
#include <string>
#include "Math.h"
#include "TGA.h"
 
// table de 162 vecteurs normaux précalculés
vec3_t CMD2Model::m_kAnorms[ NUMVERTEXNORMALS ] = {
#include    "anorms.h"
};
 
//-constructeur----------------
CMD2Model::CMD2Model( void )
{
}
 
//-destructeur-----------------
CMD2Model::~CMD2Model( void ) 
{ 
FreeModel(); 
}
 
//-constructeur----------------
CEntity::CEntity( void )
{
}
 
//-destructeur-----------------
CEntity::~CEntity( void )
{
}
 
// ----------------------------------------------
// LoadModel() - charge un modèle à partir d'un
// fichier <.md2>.
// ----------------------------------------------
bool CMD2Model::LoadModel( std::string szFilename )
{
    std::fstream    file;   // fichier
 
    // tentative d'ouverture du fichier
    file.open( szFilename.c_str(), std::ios::in | std::ios::binary );
 
    if( file.fail() )
        return false;
 
    // lecture du header
    file.read( (char *)&m_kHeader, sizeof( md2_header_t ) );
 
    // vérification de l'authenticité du modèle
    if( (m_kHeader.version != MD2_VERSION) || m_kHeader.ident != MD2_IDENT )
        return false;
 
 
    // allocation de mémoire pour les données du modèle
    m_pSkins = new md2_skin_t[ m_kHeader.num_skins ];
    m_pTexCoords = new md2_texCoord_t[ m_kHeader.num_st ];
    m_pTriangles = new md2_triangle_t[ m_kHeader.num_tris ];
    m_pFrames = new md2_frame_t[ m_kHeader.num_frames ];
    m_pGLcmds = new int[ m_kHeader.num_glcmds ];
 
    // lecture des noms de skins
    file.seekg( m_kHeader.offset_skins, std::ios::beg );
    file.read( (char *)m_pSkins, sizeof( char ) * 68 * m_kHeader.num_skins );
 
    // lecture des coordonnées de texture
    file.seekg( m_kHeader.offset_st, std::ios::beg );
    file.read( (char *)m_pTexCoords, sizeof( md2_texCoord_t ) * m_kHeader.num_st );
 
    // lecture des triangles
    file.seekg( m_kHeader.offset_tris, std::ios::beg );
    file.read( (char *)m_pTriangles, sizeof( md2_triangle_t ) * m_kHeader.num_tris );
 
    // lecture des frames
    file.seekg( m_kHeader.offset_frames, std::ios::beg );
 
    for( int i = 0; i < m_kHeader.num_frames; i++ )
    {
        // allocation de mémoire pour les vertices
        m_pFrames[i].verts = new md2_vertex_t[ m_kHeader.num_vertices ];
 
        // lecture des données de la frame
        file.read( (char *)&m_pFrames[i].scale, sizeof( vec3_t ) );
        file.read( (char *)&m_pFrames[i].translate, sizeof( vec3_t ) );
        file.read( (char *)&m_pFrames[i].name, sizeof( char ) * 16 );
        file.read( (char *)m_pFrames[i].verts, sizeof( md2_vertex_t ) * m_kHeader.num_vertices );
    }
 
    // lecture des commandes opengl
    file.seekg( m_kHeader.offset_glcmds, std::ios::beg );
    file.read( (char *)m_pGLcmds, sizeof( int ) * m_kHeader.num_glcmds );
 
 
    // fermeture du fichier
    file.close();
 
    // succès
    return true;
}
 
// ----------------------------------------------
// LoadTextures() - charge la texture du modèle
// à partir du chemin d'accès spécifié.
// ----------------------------------------------
 
void CMD2Model::LoadTexture( TGA *Texture )
{
    // chargement de la texture
    m_uiTexID = Texture->texID;
}
 
// ----------------------------------------------
// FreeModel() - libère la mémoire allouée pour
// le modèle.
// ----------------------------------------------
 
void CMD2Model::FreeModel( void )
{
    if( m_pSkins )
        delete [] m_pSkins;
 
    if( m_pTexCoords )
        delete [] m_pTexCoords;
 
    if( m_pTriangles )
        delete [] m_pTriangles;
 
    if( m_pFrames )
    {
        for( int i = 0; i < m_kHeader.num_frames; i++ )
        {
            if( m_pFrames[i].verts )
                delete [] m_pFrames[i].verts;
        }
 
        delete [] m_pFrames;
    }
}
 
// ----------------------------------------------
// RenderFrame() - dessine le modèle à la frame
// spécifiée.
// ----------------------------------------------
 
void CMD2Model::RenderFrame( int iFrame )
{
    // calcul de l'index maximum d'une frame du modèle
    int iMaxFrame = m_kHeader.num_frames - 1;
 
    // vérification de la validité de iFrame
    if( (iFrame < 0) || (iFrame > iMaxFrame) )
        return;
 
 
    // activation de la texture du modèle
    glBindTexture( GL_TEXTURE_2D, m_uiTexID );
 
    // dessin du modèle
    glBegin( GL_TRIANGLES );
        // dessine chaque triangle
        for( int i = 0; i < m_kHeader.num_tris; i++ )
        {
            // dessigne chaque vertex du triangle
            for( int k = 0; k < 3; k++ )
            {
                md2_frame_t *pFrame = &m_pFrames[ iFrame ];
                md2_vertex_t *pVert = &pFrame->verts[ m_pTriangles[i].vertex[k] ];
 
 
                // [coordonnées de texture]
                GLfloat s = (GLfloat)m_pTexCoords[ m_pTriangles[i].st[k] ].s / m_kHeader.skinwidth;
                GLfloat t = (GLfloat)m_pTexCoords[ m_pTriangles[i].st[k] ].t / m_kHeader.skinheight;
 
                // application des coordonnées de texture
                glTexCoord2f( s, t );
 
                // [normale]
                glNormal3fv( m_kAnorms[ pVert->normalIndex ] );
 
                // [vertex]
                vec3_t v;
 
                // calcul de la position absolue du vertex et redimensionnement
                v[0] = (pFrame->scale[0] * pVert->v[0] + pFrame->translate[0]) * m_fScale;
                v[1] = (pFrame->scale[1] * pVert->v[1] + pFrame->translate[1]) * m_fScale;
                v[2] = (pFrame->scale[2] * pVert->v[2] + pFrame->translate[2]) * m_fScale;
 
                glVertex3fv( v );
            }
        }
    glEnd();
}
 
// ----------------------------------------------
// DrawModelItp() - dessine le modèle avec une
// interpolation de deux frames données.
// ----------------------------------------------
 
void CMD2Model::DrawModelItp( int iFrameA, int iFrameB, float fInterp )
{
    // calcul de l'index maximum d'une frame du modèle
    int iMaxFrame = m_kHeader.num_frames - 1;
 
    // vérification de la validité des indices de frame
    if( (iFrameA < 0) || (iFrameB < 0) )
        return;
 
    if( (iFrameA > iMaxFrame) || (iFrameB > iMaxFrame) )
        return;
 
 
    // activation de la texture du modèle
    glBindTexture( GL_TEXTURE_2D, m_uiTexID );
 
    // dessin du modèle
    glBegin( GL_TRIANGLES );
        // dessine chaque triangle
        for( int i = 0; i < m_kHeader.num_tris; i++ )
        {
            // dessigne chaque vertex du triangle
            for( int k = 0; k < 3; k++ )
            {
                md2_frame_t *pFrameA = &m_pFrames[ iFrameA ];
                md2_frame_t *pFrameB = &m_pFrames[ iFrameB ];
 
                md2_vertex_t *pVertA = &pFrameA->verts[ m_pTriangles[i].vertex[k] ];
                md2_vertex_t *pVertB = &pFrameB->verts[ m_pTriangles[i].vertex[k] ];
 
 
                // [coordonnées de texture]
                GLfloat s = (GLfloat)m_pTexCoords[ m_pTriangles[i].st[k] ].s / m_kHeader.skinwidth;
                GLfloat t = (GLfloat)m_pTexCoords[ m_pTriangles[i].st[k] ].t / m_kHeader.skinheight;
 
                // application des coordonnées de texture
                glTexCoord2f( s, t );
 
                // [normale]
                vec3_t normA, normB, n;
 
                memcpy( normA, m_kAnorms[ pVertA->normalIndex ], 3 * sizeof( float ) );
                memcpy( normB, m_kAnorms[ pVertB->normalIndex ], 3 * sizeof( float ) );
 
                // interpolation linéaire
                n[0] = normA[0] + fInterp * (normB[0] - normA[0]);
                n[1] = normA[1] + fInterp * (normB[1] - normA[1]);
                n[2] = normA[2] + fInterp * (normB[2] - normA[2]);
 
                // spécification de la normale
                glNormal3fv( n );
 
                // [vertex]
                vec3_t vecA, vecB, v;
 
                // calcul de la position absolue des vertices
                vecA[0] = pFrameA->scale[0] * pVertA->v[0] + pFrameA->translate[0];
                vecA[1] = pFrameA->scale[1] * pVertA->v[1] + pFrameA->translate[1];
                vecA[2] = pFrameA->scale[2] * pVertA->v[2] + pFrameA->translate[2];
 
                vecB[0] = pFrameB->scale[0] * pVertB->v[0] + pFrameB->translate[0];
                vecB[1] = pFrameB->scale[1] * pVertB->v[1] + pFrameB->translate[1];
                vecB[2] = pFrameB->scale[2] * pVertB->v[2] + pFrameB->translate[2];
 
                // interpolation linéaire et redimensionnement
                v[0] = (vecA[0] + fInterp * (vecB[0] - vecA[0])) * m_fScale;
                v[1] = (vecA[1] + fInterp * (vecB[1] - vecA[1])) * m_fScale;
                v[2] = (vecA[2] + fInterp * (vecB[2] - vecA[2])) * m_fScale;
 
                // dessin du vertex
                glVertex3fv( v );
            }
        }
    glEnd();
}
 
// ----------------------------------------------
// Animate() - calcul les frames courante et
// suivante à partir des frames de début et de
// fin d'animation et du pourcentage d'interpolation.
// ----------------------------------------------
 
void CEntity::Animate( int iStartFrame, int iEndFrame, float fPercent )
{
    // m_iCurrFrame doit être compris entre iStartFrame et iEndFrame
    if( m_iCurrFrame < iStartFrame )
        m_iCurrFrame = iStartFrame;
 
    if( m_iCurrFrame > iEndFrame )
        m_iCurrFrame = iStartFrame;
 
    m_fPercent = fPercent;
 
    // animation : calcul des frames courante et suivante
    if( m_fInterp >= 1.0 )
    {
        m_fInterp = 0.0f;
        m_iCurrFrame++;
 
        if( m_iCurrFrame >= iEndFrame )
            m_iCurrFrame = iStartFrame;
 
        m_iNextFrame = m_iCurrFrame + 1;
 
        if( m_iNextFrame >= iEndFrame )
            m_iNextFrame = iStartFrame;
    }
}
 
// ----------------------------------------------
// DrawEntity() - dessine le modèle de l'entitée.
// si le modèle n'est pas animé, on dessine la
// frame iFrame. Si cette dernière est négative,
// on dessine la frame courante.
// ----------------------------------------------
 
void CEntity::DrawEntity( int iFrame, bool bAnimated, bool bUseGLCmds )
{
    glPushMatrix();
        // rotation des axes
        glRotatef( -90.0, 1.0, 0.0, 0.0 );
        glRotatef( -90.0, 0.0, 0.0, 1.0 );
 
        // redimensionnement du modèle
        m_pModel->SetScale( m_fScale );
 
 
        // rendu du modèle
        if( bAnimated )
        {
            // dessine chaque triangle du modèle
            m_pModel->DrawModelItp( m_iCurrFrame, m_iNextFrame, m_fInterp );
 
            // incrémentation du pourcentage d'interpolation entre les deux frames
            m_fInterp += m_fPercent;
        }
        else
        {
            // dessine chaque triangle du modèle
            if( iFrame == -1 )
                m_pModel->RenderFrame( m_iCurrFrame );
            else
                m_pModel->RenderFrame( iFrame );
        }
 
    glPopMatrix();
}
Si quelqu'un connait un lien vers une source de loader de MD2 sans SDL et sans GLUT, je suis preneur.

Merci
MProg