]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/md3model/md3.cpp
Merge remote-tracking branch 'github/master'
[xonotic/netradiant.git] / plugins / md3model / md3.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "md3.h"
23
24 #include "ifilesystem.h"
25 #include "imodel.h"
26
27 #include "imagelib.h"
28 #include "bytestreamutils.h"
29
30 #include "model.h"
31 #include "ident.h"
32 #include "md3normals.h"
33
34 // the maximum size of game reletive pathnames
35 #define MAX_QPATH       64
36
37 /*
38    ========================================================================
39
40    .MD3 triangle model file format
41
42    ========================================================================
43  */
44
45 const unsigned char MD3_IDENT[4] = { 'I', 'D', 'P', '3', };
46 #define MD3_VERSION         15
47
48 // limits
49 #define MD3_MAX_LODS        4
50 #define MD3_MAX_TRIANGLES   8192    // per surface
51 #define MD3_MAX_VERTS       4096    // per surface
52 #define MD3_MAX_SHADERS     256     // per surface
53 #define MD3_MAX_FRAMES      1024    // per model
54 #define MD3_MAX_SURFACES    32      // per model
55 #define MD3_MAX_TAGS        16      // per frame
56
57 // vertex scales
58 #define MD3_XYZ_SCALE       ( 1.f / 64 )
59
60 typedef float float3[3];
61
62 void istream_read_float3( PointerInputStream& inputStream, float3 f ){
63         f[0] = istream_read_float32_le( inputStream );
64         f[1] = istream_read_float32_le( inputStream );
65         f[2] = istream_read_float32_le( inputStream );
66 }
67
68 typedef struct md3Frame_s {
69         float3 bounds[2];
70         float3 localOrigin;
71         float radius;
72         char name[16];
73 } md3Frame_t;
74
75 void istream_read_md3Frame( PointerInputStream& inputStream, md3Frame_t& frame ){
76         istream_read_float3( inputStream, frame.bounds[0] );
77         istream_read_float3( inputStream, frame.bounds[1] );
78         istream_read_float3( inputStream, frame.localOrigin );
79         frame.radius = istream_read_float32_le( inputStream );
80         inputStream.read( reinterpret_cast<unsigned char*>( frame.name ), 16 );
81 }
82
83 typedef struct md3Tag_s {
84         char name[MAX_QPATH];           // tag name
85         float3 origin;
86         float3 axis[3];
87 } md3Tag_t;
88
89 void istream_read_md3Shader( PointerInputStream& inputStream, md3Tag_t& tag ){
90         inputStream.read( reinterpret_cast<unsigned char*>( tag.name ), MAX_QPATH );
91         istream_read_float3( inputStream, tag.origin );
92         istream_read_float3( inputStream, tag.axis[0] );
93         istream_read_float3( inputStream, tag.axis[1] );
94         istream_read_float3( inputStream, tag.axis[2] );
95 }
96
97 /*
98 ** md3Surface_t
99 **
100 ** CHUNK                        SIZE
101 ** header                       sizeof( md3Surface_t )
102 ** shaders                      sizeof( md3Shader_t ) * numShaders
103 ** triangles[0]         sizeof( md3Triangle_t ) * numTriangles
104 ** st                           sizeof( md3St_t ) * numVerts
105 ** XyzNormals           sizeof( md3XyzNormal_t ) * numVerts * numFrames
106 */
107 typedef struct {
108         char ident[4];              //
109
110         char name[MAX_QPATH]; // polyset name
111
112         int flags;
113         int numFrames; // all surfaces in a model should have the same
114
115         int numShaders; // all surfaces in a model should have the same
116         int numVerts;
117
118         int numTriangles;
119         int ofsTriangles;
120
121         int ofsShaders; // offset from start of md3Surface_t
122         int ofsSt; // texture coords are common for all frames
123         int ofsXyzNormals; // numVerts * numFrames
124
125         int ofsEnd; // next surface follows
126 } md3Surface_t;
127
128 void istream_read_md3Surface( PointerInputStream& inputStream, md3Surface_t& surface ){
129         inputStream.read( reinterpret_cast<unsigned char*>( surface.ident ), 4 );
130         inputStream.read( reinterpret_cast<unsigned char*>( surface.name ), MAX_QPATH );
131         surface.flags = istream_read_int32_le( inputStream );
132         surface.numFrames = istream_read_int32_le( inputStream );
133         surface.numShaders = istream_read_int32_le( inputStream );
134         surface.numVerts = istream_read_int32_le( inputStream );
135         surface.numTriangles = istream_read_int32_le( inputStream );
136         surface.ofsTriangles = istream_read_int32_le( inputStream );
137         surface.ofsShaders = istream_read_int32_le( inputStream );
138         surface.ofsSt = istream_read_int32_le( inputStream );
139         surface.ofsXyzNormals = istream_read_int32_le( inputStream );
140         surface.ofsEnd = istream_read_int32_le( inputStream );
141 }
142
143 typedef struct {
144         char name[MAX_QPATH];
145         int shaderIndex;                // for in-game use
146 } md3Shader_t;
147
148 void istream_read_md3Shader( PointerInputStream& inputStream, md3Shader_t& shader ){
149         inputStream.read( reinterpret_cast<unsigned char*>( shader.name ), MAX_QPATH );
150         shader.shaderIndex = istream_read_int32_le( inputStream );
151 }
152
153 typedef struct {
154         int indexes[3];
155 } md3Triangle_t;
156
157 void istream_read_md3Triangle( PointerInputStream& inputStream, md3Triangle_t& triangle ){
158         triangle.indexes[0] = istream_read_int32_le( inputStream );
159         triangle.indexes[1] = istream_read_int32_le( inputStream );
160         triangle.indexes[2] = istream_read_int32_le( inputStream );
161 }
162
163 typedef struct {
164         float st[2];
165 } md3St_t;
166
167 void istream_read_md3St( PointerInputStream& inputStream, md3St_t& st ){
168         st.st[0] = istream_read_float32_le( inputStream );
169         st.st[1] = istream_read_float32_le( inputStream );
170 }
171
172 typedef struct {
173         short xyz[3];
174         short normal;
175 } md3XyzNormal_t;
176
177 void istream_read_md3XyzNormal( PointerInputStream& inputStream, md3XyzNormal_t& xyz ){
178         xyz.xyz[0] = istream_read_int16_le( inputStream );
179         xyz.xyz[1] = istream_read_int16_le( inputStream );
180         xyz.xyz[2] = istream_read_int16_le( inputStream );
181         xyz.normal = istream_read_int16_le( inputStream );
182 }
183
184 typedef struct {
185         char ident[4];
186         int version;
187
188         char name[MAX_QPATH];           // model name
189
190         int flags;
191
192         int numFrames;
193         int numTags;
194         int numSurfaces;
195
196         int numSkins;
197
198         int ofsFrames;                  // offset for first frame
199         int ofsTags;                    // numFrames * numTags
200         int ofsSurfaces;                // first surface, others follow
201
202         int ofsEnd;                     // end of file
203 } md3Header_t;
204
205 void istream_read_md3Header( PointerInputStream& inputStream, md3Header_t& header ){
206         inputStream.read( reinterpret_cast<unsigned char*>( header.ident ), 4 );
207         header.version = istream_read_int32_le( inputStream );
208         inputStream.read( reinterpret_cast<unsigned char*>( header.name ), MAX_QPATH );
209         header.flags = istream_read_int32_le( inputStream );
210         header.numFrames = istream_read_int32_le( inputStream );
211         header.numTags = istream_read_int32_le( inputStream );
212         header.numSurfaces = istream_read_int32_le( inputStream );
213         header.numSkins = istream_read_int32_le( inputStream );
214         header.ofsFrames = istream_read_int32_le( inputStream );
215         header.ofsTags = istream_read_int32_le( inputStream );
216         header.ofsSurfaces = istream_read_int32_le( inputStream );
217         header.ofsEnd = istream_read_int32_le( inputStream );
218 }
219
220 int MD3Surface_read( Surface& surface, unsigned char* buffer ){
221         md3Surface_t md3Surface;
222         {
223                 PointerInputStream inputStream( buffer );
224                 istream_read_md3Surface( inputStream, md3Surface );
225         }
226
227         {
228                 surface.vertices().reserve( md3Surface.numVerts );
229
230                 PointerInputStream xyzNormalStream( buffer + md3Surface.ofsXyzNormals );
231                 PointerInputStream stStream( buffer + md3Surface.ofsSt );
232
233                 // read verts into vertex array - xyz, st, normal
234                 for ( int i = 0; i < md3Surface.numVerts; i++ )
235                 {
236                         md3XyzNormal_t md3Xyz;
237                         istream_read_md3XyzNormal( xyzNormalStream, md3Xyz );
238
239                         md3St_t md3St;
240                         istream_read_md3St( stStream, md3St );
241
242                         surface.vertices().push_back(
243                                 ArbitraryMeshVertex(
244                                         Vertex3f( md3Xyz.xyz[0] * MD3_XYZ_SCALE, md3Xyz.xyz[1] * MD3_XYZ_SCALE, md3Xyz.xyz[2] * MD3_XYZ_SCALE ),
245                                         DecodeNormal( reinterpret_cast<byte*>( &md3Xyz.normal ) ),
246                                         TexCoord2f( md3St.st[0], md3St.st[1] )
247                                         )
248                                 );
249                 }
250         }
251
252         {
253                 surface.indices().reserve( md3Surface.numTriangles * 3 );
254
255                 PointerInputStream inputStream( buffer + md3Surface.ofsTriangles );
256                 for ( int i = 0; i < md3Surface.numTriangles; i++ )
257                 {
258                         md3Triangle_t md3Triangle;
259                         istream_read_md3Triangle( inputStream, md3Triangle );
260                         surface.indices().insert( md3Triangle.indexes[0] );
261                         surface.indices().insert( md3Triangle.indexes[1] );
262                         surface.indices().insert( md3Triangle.indexes[2] );
263                 }
264         }
265
266         {
267                 md3Shader_t md3Shader;
268                 {
269                         PointerInputStream inputStream( buffer + md3Surface.ofsShaders );
270                         istream_read_md3Shader( inputStream, md3Shader );
271                 }
272                 surface.setShader( md3Shader.name );
273         }
274
275         surface.updateAABB();
276
277         return md3Surface.ofsEnd;
278 }
279
280 void MD3Model_read( Model& model, unsigned char* buffer ){
281         md3Header_t md3Header;
282         {
283                 PointerInputStream inputStream( buffer );
284                 istream_read_md3Header( inputStream, md3Header );
285         }
286
287         unsigned char* surfacePosition = buffer + md3Header.ofsSurfaces;
288
289         for ( int i = 0; i != md3Header.numSurfaces; ++i )
290         {
291                 surfacePosition += MD3Surface_read( model.newSurface(), surfacePosition );
292         }
293
294         model.updateAABB();
295 }
296
297 scene::Node& MD3Model_new( unsigned char* buffer ){
298         ModelNode* modelNode = new ModelNode();
299         MD3Model_read( modelNode->model(), buffer );
300         return modelNode->node();
301 }
302
303 scene::Node& MD3Model_default(){
304         ModelNode* modelNode = new ModelNode();
305         Model_constructNull( modelNode->model() );
306         return modelNode->node();
307 }
308
309 scene::Node& MD3Model_fromBuffer( unsigned char* buffer ){
310         if ( !ident_equal( buffer, MD3_IDENT ) ) {
311                 globalErrorStream() << "MD3 read error: incorrect ident\n";
312                 return MD3Model_default();
313         }
314         else
315         {
316                 return MD3Model_new( buffer );
317         }
318 }
319
320 scene::Node& loadMD3Model( ArchiveFile& file ){
321         ScopedArchiveBuffer buffer( file );
322         return MD3Model_fromBuffer( buffer.buffer );
323 }