1 //********************************************************************************************
2 //*
3 //* This file is part of id_md2 reader library.
4 //*
5 //* Egoboo is free software: you can redistribute it and/or modify it
6 //* under the terms of the GNU General Public License as published by
7 //* the Free Software Foundation, either version 3 of the License, or
8 //* (at your option) any later version.
9 //*
10 //* Egoboo is distributed in the hope that it will be useful, but
11 //* WITHOUT ANY WARRANTY; without even the implied warranty of
12 //* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 //* General Public License for more details.
14 //*
15 //* You should have received a copy of the GNU General Public License
16 //* along with Egoboo. If not, see <http://www.gnu.org/licenses/>.
17 //*
18 //********************************************************************************************
19
20 /// @file file_formats/id_md2.c
21 /// @brief A raw reader and writer for ID software's .md2 model type
22 /// @details
23
24 #include "id_md2.h"
25 #include "egoboo_vfs.h"
26
27 #include <stdlib.h>
28
29 //--------------------------------------------------------------------------------------------
30 //--------------------------------------------------------------------------------------------
31 /* Table of precalculated normals */
32 float kid_md2_normals[MD2_MAX_NORMALS][3] =
33 {
34 # include "id_normals.inl"
35 };
36
37 //--------------------------------------------------------------------------------------------
38 //--------------------------------------------------------------------------------------------
39
40 /// Load an MD2 model from file.
41 ///
42 /// @note MD2 format stores model's data in little-endian ordering. On
43 /// big-endian machines, you'll have to perform proper conversions.
44
id_md2_load(const char * filename,id_md2_model_t * mdl)45 id_md2_model_t * id_md2_load( const char *filename, id_md2_model_t * mdl )
46 {
47 FILE *fp;
48 int i;
49
50 fp = fopen( filename, "rb" );
51 if ( !fp )
52 {
53 fprintf( stderr, "Error: couldn't open \"%s\"!\n", filename );
54 return 0;
55 }
56
57 if ( NULL == mdl )
58 {
59 mdl = ( id_md2_model_t* )calloc( 1, sizeof( id_md2_model_t ) );
60 }
61
62 if ( NULL == mdl ) return NULL;
63
64 /* Read header */
65 fread( &mdl->header, 1, sizeof( id_md2_header_t ), fp );
66
67 if (( mdl->header.ident != MD2_MAGIC_NUMBER ) ||
68 ( mdl->header.version != MD2_VERSION ) )
69 {
70 /* Error! */
71 fprintf( stderr, "Error: bad version or identifier\n" );
72 fclose( fp );
73 return 0;
74 }
75
76 /* Memory allocations */
77 mdl->skins = ( id_md2_skin_t * ) calloc( mdl->header.num_skins, sizeof( id_md2_skin_t ) );
78 mdl->texcoords = ( id_md2_texcoord_t * ) calloc( mdl->header.num_st, sizeof( id_md2_texcoord_t ) );
79 mdl->triangles = ( id_md2_triangle_t * ) calloc( mdl->header.num_tris, sizeof( id_md2_triangle_t ) );
80 mdl->frames = ( id_md2_frame_t * ) calloc( mdl->header.num_frames, sizeof( id_md2_frame_t ) );
81 mdl->glcmds = ( int * ) calloc( mdl->header.size_glcmds, sizeof( int ) );
82
83 /* Read model data */
84 fseek( fp, mdl->header.offset_skins, SEEK_SET );
85 fread( mdl->skins, sizeof( id_md2_skin_t ), mdl->header.num_skins, fp );
86
87 fseek( fp, mdl->header.offset_st, SEEK_SET );
88 fread( mdl->texcoords, sizeof( id_md2_texcoord_t ), mdl->header.num_st, fp );
89
90 fseek( fp, mdl->header.offset_tris, SEEK_SET );
91 fread( mdl->triangles, sizeof( id_md2_triangle_t ), mdl->header.num_tris, fp );
92
93 fseek( fp, mdl->header.offset_glcmds, SEEK_SET );
94 fread( mdl->glcmds, sizeof( int ), mdl->header.size_glcmds, fp );
95
96 /* Read frames */
97 fseek( fp, mdl->header.offset_frames, SEEK_SET );
98 for ( i = 0; i < mdl->header.num_frames; ++i )
99 {
100 /* Memory allocation for vertices of this frame */
101 mdl->frames[i].verts = ( id_md2_vertex_t * )calloc( mdl->header.num_vertices, sizeof( id_md2_vertex_t ) );
102
103 /* Read frame data */
104 fread( mdl->frames[i].scale, sizeof( float ), 3, fp );
105 fread( mdl->frames[i].translate, sizeof( float ), 3, fp );
106 fread( mdl->frames[i].name, sizeof( char ), 16, fp );
107 fread( mdl->frames[i].verts, sizeof( id_md2_vertex_t ), mdl->header.num_vertices, fp );
108 }
109
110 fclose( fp );
111 return mdl;
112 }
113
114 //--------------------------------------------------------------------------------------------
115 // Free resources allocated for the model.
116
id_md2_free(id_md2_model_t * mdl)117 void id_md2_free( id_md2_model_t * mdl )
118 {
119 int i;
120
121 if ( mdl->skins )
122 {
123 free( mdl->skins );
124 mdl->skins = NULL;
125 }
126
127 if ( mdl->texcoords )
128 {
129 free( mdl->texcoords );
130 mdl->texcoords = NULL;
131 }
132
133 if ( mdl->triangles )
134 {
135 free( mdl->triangles );
136 mdl->triangles = NULL;
137 }
138
139 if ( mdl->glcmds )
140 {
141 free( mdl->glcmds );
142 mdl->glcmds = NULL;
143 }
144
145 if ( mdl->frames )
146 {
147 for ( i = 0; i < mdl->header.num_frames; ++i )
148 {
149 free( mdl->frames[i].verts );
150 mdl->frames[i].verts = NULL;
151 }
152
153 free( mdl->frames );
154 mdl->frames = NULL;
155 }
156 }
157