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