Merge commit '830125fad042fad35dc029b6eb57c8156ad7e176'
[xonotic/netradiant.git] / plugins / md3model / mdc.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 "mdc.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
35 const unsigned char MDC_IDENT[4] = { 'I', 'D', 'P', 'C', };
36 const float MDC_XYZ_SCALE = 0.015625f;
37 #define MAX_QPATH           64      // max length of a quake game pathname
38
39 typedef float float3[3];
40
41 struct mdcTriangle_t
42 {
43         unsigned int indexes[3]; // not my spelling
44 };
45
46 void istream_read_mdcTriangle( PointerInputStream& inputStream, mdcTriangle_t& triangle ){
47         triangle.indexes[0] = istream_read_uint32_le( inputStream );
48         triangle.indexes[1] = istream_read_uint32_le( inputStream );
49         triangle.indexes[2] = istream_read_uint32_le( inputStream );
50 }
51
52 struct mdcXyzNormal_t
53 {
54         short xyz[3]; // divide by 64
55         short normal; // packed same way as md3
56 };
57
58 void istream_read_mdcXyzNormal( PointerInputStream& inputStream, mdcXyzNormal_t& xyz ){
59         xyz.xyz[0] = istream_read_int16_le( inputStream );
60         xyz.xyz[1] = istream_read_int16_le( inputStream );
61         xyz.xyz[2] = istream_read_int16_le( inputStream );
62         xyz.normal = istream_read_int16_le( inputStream );
63 }
64
65 struct mdcSt_t
66 {
67         float st[2]; // may need to reverse t
68 };
69
70 void istream_read_mdcSt( PointerInputStream& inputStream, mdcSt_t& st ){
71         st.st[0] = istream_read_float32_le( inputStream );
72         st.st[1] = istream_read_float32_le( inputStream );
73 }
74
75 struct mdcShader_t
76 {
77         char name[MAX_QPATH];
78         unsigned int flags;
79 };
80
81 void istream_read_mdcShader( PointerInputStream& inputStream, mdcShader_t& shader ){
82         inputStream.read( reinterpret_cast<byte*>( shader.name ), MAX_QPATH );
83         shader.flags = istream_read_uint32_le( inputStream );
84 }
85
86 struct mdcTagName_t
87 {
88         char name[MAX_QPATH];
89 };
90
91 struct mdcTagFrame_t
92 {
93         short xyz[3]; // divide by 64
94         short angles[3]; // euler in z x y order...   deg = * (360.0 / 32767.0) .. rad = * (PI / 32767.0)
95 };
96
97 struct mdcFrame_t
98 {
99         float3 bboxMin;
100         float3 bboxMax;
101         float3 localOrigin;
102         float radius;
103         char name[16];
104 };
105
106 struct mdcSurface_t
107 {
108         byte ident[4];
109         char name[MAX_QPATH];
110         unsigned int flags;
111         unsigned int numCompFrames;
112         unsigned int numBaseFrames;
113         unsigned int numShaders;
114         unsigned int numVerts;
115         unsigned int numTriangles;
116         unsigned int ofsTriangles;
117         unsigned int ofsShaders;
118         unsigned int ofsSt;
119         unsigned int ofsXyzNormals;
120         unsigned int ofsCompVerts;
121         unsigned int ofsFrameBaseFrames;
122         unsigned int ofsFrameCompFrames;
123         unsigned int ofsEnd;
124 };
125
126 void istream_read_mdcSurface( PointerInputStream& inputStream, mdcSurface_t& surface ){
127         inputStream.read( surface.ident, 4 );
128         inputStream.read( reinterpret_cast<byte*>( surface.name ), MAX_QPATH );
129         surface.flags = istream_read_uint32_le( inputStream );
130         surface.numCompFrames = istream_read_uint32_le( inputStream );
131         surface.numBaseFrames = istream_read_uint32_le( inputStream );
132         surface.numShaders = istream_read_uint32_le( inputStream );
133         surface.numVerts = istream_read_uint32_le( inputStream );
134         surface.numTriangles = istream_read_uint32_le( inputStream );
135         surface.ofsTriangles = istream_read_uint32_le( inputStream );
136         surface.ofsShaders = istream_read_uint32_le( inputStream );
137         surface.ofsSt = istream_read_uint32_le( inputStream );
138         surface.ofsXyzNormals = istream_read_uint32_le( inputStream );
139         surface.ofsCompVerts = istream_read_uint32_le( inputStream );
140         surface.ofsFrameBaseFrames = istream_read_uint32_le( inputStream );
141         surface.ofsFrameCompFrames = istream_read_uint32_le( inputStream );
142         surface.ofsEnd = istream_read_uint32_le( inputStream );
143 }
144
145 struct mdcHeader_t
146 {
147         byte ident[4];
148         unsigned int version;
149         char name[MAX_QPATH];
150         unsigned int flags;
151         unsigned int numFrames;
152         unsigned int numTags;
153         unsigned int numSurfaces;
154         unsigned int numSkins;
155         unsigned int ofsFrames;
156         unsigned int ofsTagNames;
157         unsigned int ofsTags;
158         unsigned int ofsSurfaces;
159         unsigned int ofsEnd;
160 };
161
162 void istream_read_mdcHeader( PointerInputStream& inputStream, mdcHeader_t& header ){
163         inputStream.read( header.ident, 4 );
164         header.version = istream_read_uint32_le( inputStream );
165         inputStream.read( reinterpret_cast<byte*>( header.name ), MAX_QPATH );
166         header.flags = istream_read_uint32_le( inputStream );
167         header.numFrames = istream_read_uint32_le( inputStream );
168         header.numTags = istream_read_uint32_le( inputStream );
169         header.numSurfaces = istream_read_uint32_le( inputStream );
170         header.numSkins = istream_read_uint32_le( inputStream );
171         header.ofsFrames = istream_read_uint32_le( inputStream );
172         header.ofsTagNames = istream_read_uint32_le( inputStream );
173         header.ofsTags = istream_read_uint32_le( inputStream );
174         header.ofsSurfaces = istream_read_uint32_le( inputStream );
175         header.ofsEnd = istream_read_uint32_le( inputStream );
176 }
177
178 unsigned int MDCSurface_read( Surface& surface, const byte* buffer ){
179         mdcSurface_t mdcSurface;
180         {
181                 PointerInputStream inputStream( buffer );
182                 istream_read_mdcSurface( inputStream, mdcSurface );
183         }
184
185         {
186                 surface.vertices().reserve( mdcSurface.numVerts );
187
188                 PointerInputStream xyzStream( buffer + mdcSurface.ofsXyzNormals );
189                 PointerInputStream stStream( buffer + mdcSurface.ofsSt );
190                 // read verts into vertex array - xyz, st, normal
191                 for ( std::size_t i = 0; i < mdcSurface.numVerts; i++ )
192                 {
193                         mdcXyzNormal_t mdcXyzNormal;
194                         istream_read_mdcXyzNormal( xyzStream, mdcXyzNormal );
195                         mdcSt_t mdcSt;
196                         istream_read_mdcSt( stStream, mdcSt );
197
198                         surface.vertices().push_back(
199                                 ArbitraryMeshVertex(
200                                         Vertex3f( mdcXyzNormal.xyz[0] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[1] * MDC_XYZ_SCALE, mdcXyzNormal.xyz[2] * MDC_XYZ_SCALE ),
201                                         DecodeNormal( reinterpret_cast<byte*>( &mdcXyzNormal.normal ) ),
202                                         TexCoord2f( mdcSt.st[0], mdcSt.st[1] )
203                                         )
204                                 );
205                 }
206         }
207
208         {
209                 surface.indices().reserve( mdcSurface.numTriangles * 3 );
210
211                 PointerInputStream triangleStream( buffer + mdcSurface.ofsTriangles );
212
213                 for ( std::size_t i = 0; i < mdcSurface.numTriangles; i++ )
214                 {
215                         mdcTriangle_t triangle;
216                         istream_read_mdcTriangle( triangleStream, triangle );
217                         surface.indices().insert( triangle.indexes[0] );
218                         surface.indices().insert( triangle.indexes[1] );
219                         surface.indices().insert( triangle.indexes[2] );
220                 }
221         }
222
223         {
224                 mdcShader_t shader;
225                 PointerInputStream inputStream( buffer + mdcSurface.ofsShaders );
226                 istream_read_mdcShader( inputStream, shader );
227                 surface.setShader( shader.name );
228         }
229
230         surface.updateAABB();
231
232         return mdcSurface.ofsEnd;
233 }
234
235 void MDCModel_read( Model& model, const byte* buffer ){
236         mdcHeader_t header;
237         {
238                 PointerInputStream inputStream( buffer );
239                 istream_read_mdcHeader( inputStream, header );
240         }
241
242         const byte* surfacePosition = buffer + header.ofsSurfaces;
243
244         for ( std::size_t i = 0; i < header.numSurfaces; i++ )
245         {
246                 surfacePosition += MDCSurface_read( model.newSurface(), surfacePosition );
247         }
248
249         model.updateAABB();
250 }
251
252 scene::Node& MDCModel_new( const byte* buffer ){
253         ModelNode* modelNode = new ModelNode();
254         MDCModel_read( modelNode->model(), buffer );
255         return modelNode->node();
256 }
257
258 scene::Node& MDCModel_default(){
259         ModelNode* modelNode = new ModelNode();
260         Model_constructNull( modelNode->model() );
261         return modelNode->node();
262 }
263
264 scene::Node& MDCModel_fromBuffer( unsigned char* buffer ){
265         if ( !ident_equal( buffer, MDC_IDENT ) ) {
266                 globalErrorStream() << "MDC read error: incorrect ident\n";
267                 return MDCModel_default();
268         }
269         else
270         {
271                 return MDCModel_new( buffer );
272         }
273 }
274
275 scene::Node& loadMDCModel( ArchiveFile& file ){
276         ScopedArchiveBuffer buffer( file );
277         return MDCModel_fromBuffer( buffer.buffer );
278 }