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