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 ){
36 inputStream.read( header.ident, 4 );
37 header.version = istream_read_int32_le( inputStream );
38 header.scale[0] = istream_read_float32_le( inputStream );
39 header.scale[1] = istream_read_float32_le( inputStream );
40 header.scale[2] = istream_read_float32_le( inputStream );
41 header.scale_origin[0] = istream_read_float32_le( inputStream );
42 header.scale_origin[1] = istream_read_float32_le( inputStream );
43 header.scale_origin[2] = istream_read_float32_le( inputStream );
44 header.boundingradius = istream_read_float32_le( inputStream );
45 header.eyeposition[0] = istream_read_float32_le( inputStream );
46 header.eyeposition[1] = istream_read_float32_le( inputStream );
47 header.eyeposition[2] = istream_read_float32_le( inputStream );
48 header.numskins = istream_read_int32_le( inputStream );
49 header.skinwidth = istream_read_int32_le( inputStream );
50 header.skinheight = istream_read_int32_le( inputStream );
51 header.numverts = istream_read_int32_le( inputStream );
52 header.numtris = istream_read_int32_le( inputStream );
53 header.numframes = istream_read_int32_le( inputStream );
54 header.synctype = istream_read_int32_le( inputStream );
55 header.flags = istream_read_int32_le( inputStream );
56 header.size = istream_read_float32_le( inputStream );
59 inline ArbitraryMeshVertex MDLVertex_construct( const mdlHeader_t& header, const mdlXyzNormal_t& xyz, const mdlSt_t& st, bool facesfront ){
60 return ArbitraryMeshVertex(
62 xyz.v[0] * header.scale[0] + header.scale_origin[0],
63 xyz.v[1] * header.scale[1] + header.scale_origin[1],
64 xyz.v[2] * header.scale[2] + header.scale_origin[2]
67 g_mdl_normals[xyz.lightnormalindex][0],
68 g_mdl_normals[xyz.lightnormalindex][1],
69 g_mdl_normals[xyz.lightnormalindex][2]
72 ( (float)st.s / header.skinwidth ) + ( ( st.onseam == MDL_ONSEAM && !facesfront ) ? 0.5f : 0.0f ),
73 (float)st.t / header.skinheight
81 inline mdlVertex_t( int vertindex, int facesfront )
82 : m_vertindex( vertindex ), m_facesfront( facesfront )
84 inline bool operator<( const mdlVertex_t& other ) const {
85 if ( m_facesfront < other.m_facesfront ) {
88 if ( other.m_facesfront < m_facesfront ) {
92 if ( m_vertindex < other.m_vertindex ) {
95 if ( other.m_vertindex < m_vertindex ) {
101 inline bool operator==( const mdlVertex_t& other ) const {
102 return m_vertindex == other.m_vertindex
103 && m_facesfront == other.m_facesfront;
110 typedef const mdlTriangle_t* mdlTriangleIterator;
112 void MDLSurface_read( Surface& surface, const byte* buffer, const char* name ){
115 PointerInputStream inputStream( buffer );
116 istream_read_mdlHeader( inputStream, header );
118 for ( int i = 0; i < header.numskins; ++i )
120 switch ( istream_read_int32_le( inputStream ) )
122 case MDL_SKIN_SINGLE:
123 inputStream.seek( header.skinwidth * header.skinheight );
126 int numskins = istream_read_int32_le( inputStream );
127 inputStream.seek( numskins * ( 4 + ( header.skinwidth * header.skinheight ) ) );
132 Array<mdlSt_t> mdlSts( header.numverts );
133 for ( Array<mdlSt_t>::iterator i = mdlSts.begin(); i != mdlSts.end(); ++i )
135 ( *i ).onseam = istream_read_int32_le( inputStream );
136 ( *i ).s = istream_read_int32_le( inputStream );
137 ( *i ).t = istream_read_int32_le( inputStream );
140 Array<mdlTriangle_t> mdlTriangles( header.numtris );
141 for ( Array<mdlTriangle_t>::iterator i = mdlTriangles.begin(); i != mdlTriangles.end(); ++i )
143 ( *i ).facesfront = istream_read_int32_le( inputStream );
144 ( *i ).vertindex[0] = istream_read_int32_le( inputStream );
145 ( *i ).vertindex[1] = istream_read_int32_le( inputStream );
146 ( *i ).vertindex[2] = istream_read_int32_le( inputStream );
151 for ( int i = 0; i < header.numframes && found == false; i++ )
153 switch ( istream_read_int32_le( inputStream ) )
155 case MDL_FRAME_SINGLE:
156 inputStream.seek( MDL_FRAME_SIZE );
159 case MDL_FRAME_GROUP:
160 int numframes = istream_read_int32_le( inputStream );
161 inputStream.seek( ( MDL_XYZNORMAL_SIZE * 2 ) + ( numframes * 4 ) );
168 Array<mdlXyzNormal_t> mdlXyzNormals( header.numtris );
169 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 )
182 surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[0], ( *i ).facesfront ) ) );
183 surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[1], ( *i ).facesfront ) ) );
184 surface.indices().insert( inserter.insert( mdlVertex_t( ( *i ).vertindex[2], ( *i ).facesfront ) ) );
189 surface.vertices().reserve( mdl_vertices.size() );
191 for ( VertexBuffer<mdlVertex_t>::iterator i = mdl_vertices.begin(); i != mdl_vertices.end(); ++i )
193 surface.vertices().push_back( MDLVertex_construct( header, mdlXyzNormals[( *i ).m_vertindex], mdlSts[( *i ).m_vertindex], ( *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 ){
203 MDLSurface_read( model.newSurface(), buffer, name );
207 scene::Node& MDLModel_new( const byte* buffer, const char* name ){
208 ModelNode* modelNode = new ModelNode();
209 MDLModel_read( modelNode->model(), buffer, name );
210 return modelNode->node();
213 scene::Node& MDLModel_default(){
214 ModelNode* modelNode = new ModelNode();
215 Model_constructNull( modelNode->model() );
216 return modelNode->node();
219 scene::Node& MDLModel_fromBuffer( unsigned char* buffer, const char* name ){
220 if ( !ident_equal( buffer, MDL_IDENT ) ) {
221 globalErrorStream() << "MDL read error: incorrect ident\n";
222 return MDLModel_default();
226 return MDLModel_new( buffer, name );
230 scene::Node& loadMDLModel( ArchiveFile& file ){
231 ScopedArchiveBuffer buffer( file );
232 return MDLModel_fromBuffer( buffer.buffer, file.getName() );