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