2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
24 #include "ifilesystem.h"
28 #include "bytestreamutils.h"
32 #include "mdlnormals.h"
33 #include "mdlformat.h"
35 void istream_read_mdlHeader(PointerInputStream &inputStream, mdlHeader_t &header)
37 inputStream.read(header.ident, 4);
38 header.version = istream_read_int32_le(inputStream);
39 header.scale[0] = istream_read_float32_le(inputStream);
40 header.scale[1] = istream_read_float32_le(inputStream);
41 header.scale[2] = istream_read_float32_le(inputStream);
42 header.scale_origin[0] = istream_read_float32_le(inputStream);
43 header.scale_origin[1] = istream_read_float32_le(inputStream);
44 header.scale_origin[2] = istream_read_float32_le(inputStream);
45 header.boundingradius = istream_read_float32_le(inputStream);
46 header.eyeposition[0] = istream_read_float32_le(inputStream);
47 header.eyeposition[1] = istream_read_float32_le(inputStream);
48 header.eyeposition[2] = istream_read_float32_le(inputStream);
49 header.numskins = istream_read_int32_le(inputStream);
50 header.skinwidth = istream_read_int32_le(inputStream);
51 header.skinheight = istream_read_int32_le(inputStream);
52 header.numverts = istream_read_int32_le(inputStream);
53 header.numtris = istream_read_int32_le(inputStream);
54 header.numframes = istream_read_int32_le(inputStream);
55 header.synctype = istream_read_int32_le(inputStream);
56 header.flags = istream_read_int32_le(inputStream);
57 header.size = istream_read_float32_le(inputStream);
60 inline ArbitraryMeshVertex
61 MDLVertex_construct(const mdlHeader_t &header, const mdlXyzNormal_t &xyz, const mdlSt_t &st, bool facesfront)
63 return ArbitraryMeshVertex(
65 xyz.v[0] * header.scale[0] + header.scale_origin[0],
66 xyz.v[1] * header.scale[1] + header.scale_origin[1],
67 xyz.v[2] * header.scale[2] + header.scale_origin[2]
70 g_mdl_normals[xyz.lightnormalindex][0],
71 g_mdl_normals[xyz.lightnormalindex][1],
72 g_mdl_normals[xyz.lightnormalindex][2]
75 ((float) st.s / header.skinwidth) + ((st.onseam == MDL_ONSEAM && !facesfront) ? 0.5f : 0.0f),
76 (float) st.t / header.skinheight
83 inline mdlVertex_t(int vertindex, int facesfront)
84 : m_vertindex(vertindex), m_facesfront(facesfront)
87 inline bool operator<(const mdlVertex_t &other) const
89 if (m_facesfront < other.m_facesfront) {
92 if (other.m_facesfront < m_facesfront) {
96 if (m_vertindex < other.m_vertindex) {
99 if (other.m_vertindex < m_vertindex) {
106 inline bool operator==(const mdlVertex_t &other) const
108 return m_vertindex == other.m_vertindex
109 && m_facesfront == other.m_facesfront;
116 typedef const mdlTriangle_t *mdlTriangleIterator;
118 void MDLSurface_read(Surface &surface, const byte *buffer, const char *name)
122 PointerInputStream inputStream(buffer);
123 istream_read_mdlHeader(inputStream, header);
125 for (int i = 0; i < header.numskins; ++i) {
126 switch (istream_read_int32_le(inputStream)) {
127 case MDL_SKIN_SINGLE:
128 inputStream.seek(header.skinwidth * header.skinheight);
131 int numskins = istream_read_int32_le(inputStream);
132 inputStream.seek(numskins * (4 + (header.skinwidth * header.skinheight)));
137 Array<mdlSt_t> mdlSts(header.numverts);
138 for (Array<mdlSt_t>::iterator i = mdlSts.begin(); i != mdlSts.end(); ++i) {
139 (*i).onseam = istream_read_int32_le(inputStream);
140 (*i).s = istream_read_int32_le(inputStream);
141 (*i).t = istream_read_int32_le(inputStream);
144 Array<mdlTriangle_t> mdlTriangles(header.numtris);
145 for (Array<mdlTriangle_t>::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i) {
146 (*i).facesfront = istream_read_int32_le(inputStream);
147 (*i).vertindex[0] = istream_read_int32_le(inputStream);
148 (*i).vertindex[1] = istream_read_int32_le(inputStream);
149 (*i).vertindex[2] = istream_read_int32_le(inputStream);
154 for (int i = 0; i < header.numframes && found == false; i++) {
155 switch (istream_read_int32_le(inputStream)) {
156 case MDL_FRAME_SINGLE:
157 inputStream.seek(MDL_FRAME_SIZE);
160 case MDL_FRAME_GROUP:
161 int numframes = istream_read_int32_le(inputStream);
162 inputStream.seek((MDL_XYZNORMAL_SIZE * 2) + (numframes * 4));
169 Array<mdlXyzNormal_t> mdlXyzNormals(header.numtris);
170 for (Array<mdlXyzNormal_t>::iterator i = mdlXyzNormals.begin(); i != mdlXyzNormals.end(); ++i) {
171 inputStream.read((*i).v, 3);
172 inputStream.read(&(*i).lightnormalindex, 1);
176 VertexBuffer<mdlVertex_t> mdl_vertices;
179 UniqueVertexBuffer<mdlVertex_t> inserter(mdl_vertices);
180 for (Array<mdlTriangle_t>::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i) {
181 surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[0], (*i).facesfront)));
182 surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[1], (*i).facesfront)));
183 surface.indices().insert(inserter.insert(mdlVertex_t((*i).vertindex[2], (*i).facesfront)));
188 surface.vertices().reserve(mdl_vertices.size());
190 for (VertexBuffer<mdlVertex_t>::iterator i = mdl_vertices.begin(); i != mdl_vertices.end(); ++i) {
191 surface.vertices().push_back(
192 MDLVertex_construct(header, mdlXyzNormals[(*i).m_vertindex], mdlSts[(*i).m_vertindex],
193 (*i).m_facesfront == MDL_FACES_FRONT));
198 surface.setShader(name);
199 surface.updateAABB();
202 void MDLModel_read(Model &model, const byte *buffer, const char *name)
204 MDLSurface_read(model.newSurface(), buffer, name);
208 scene::Node &MDLModel_new(const byte *buffer, const char *name)
210 ModelNode *modelNode = new ModelNode();
211 MDLModel_read(modelNode->model(), buffer, name);
212 return modelNode->node();
215 scene::Node &MDLModel_default()
217 ModelNode *modelNode = new ModelNode();
218 Model_constructNull(modelNode->model());
219 return modelNode->node();
222 scene::Node &MDLModel_fromBuffer(unsigned char *buffer, const char *name)
224 if (!ident_equal(buffer, MDL_IDENT)) {
225 globalErrorStream() << "MDL read error: incorrect ident\n";
226 return MDLModel_default();
228 return MDLModel_new(buffer, name);
232 scene::Node &loadMDLModel(ArchiveFile &file)
234 ScopedArchiveBuffer buffer(file);
235 return MDLModel_fromBuffer(buffer.buffer, file.getName());