X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=plugins%2Fmd3model%2Fmd2.cpp;h=56a18ddc254e5e435221805a89adfd1563882c9b;hp=55a32f5fb9d29a835dd6d9ea93fbb3423c791107;hb=3c73487420fde8d4a3b5360d8b99e48132517900;hpb=12c13001257458f2ce361e6d24958264a816153b diff --git a/plugins/md3model/md2.cpp b/plugins/md3model/md2.cpp index 55a32f5f..56a18ddc 100644 --- a/plugins/md3model/md2.cpp +++ b/plugins/md3model/md2.cpp @@ -1,23 +1,23 @@ /* -Copyright (C) 2001-2006, William Joseph. -All Rights Reserved. + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "md2.h" @@ -34,62 +34,59 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA typedef unsigned char byte; /* -======================================================================== + ======================================================================== -.MD2 triangle model file format + .MD2 triangle model file format -======================================================================== -*/ + ======================================================================== + */ #define MD2_NUMVERTEXNORMALS 162 -#define MD2_MAX_SKINNAME 64 +#define MD2_MAX_SKINNAME 64 const unsigned char MD2_IDENT[4] = { 'I', 'D', 'P', '2', }; -#define MD2_VERSION 8 +#define MD2_VERSION 8 -#define MD2_MAX_TRIANGLES 4096 -#define MD2_MAX_VERTS 2048 -#define MD2_MAX_FRAMES 512 -#define MD2_MAX_MD2SKINS 32 -#define MD2_MAX_SKINNAME 64 +#define MD2_MAX_TRIANGLES 4096 +#define MD2_MAX_VERTS 2048 +#define MD2_MAX_FRAMES 512 +#define MD2_MAX_MD2SKINS 32 +#define MD2_MAX_SKINNAME 64 typedef struct { - short s; - short t; + short s; + short t; } md2St_t; -void istream_read_md2St(PointerInputStream& inputStream, md2St_t& st) -{ - st.s = istream_read_int16_le(inputStream); - st.t = istream_read_int16_le(inputStream); +void istream_read_md2St( PointerInputStream& inputStream, md2St_t& st ){ + st.s = istream_read_int16_le( inputStream ); + st.t = istream_read_int16_le( inputStream ); } -typedef struct +typedef struct { - short index_xyz[3]; - short index_st[3]; + short index_xyz[3]; + short index_st[3]; } md2Triangle_t; -void istream_read_md2Triangle(PointerInputStream& inputStream, md2Triangle_t& triangle) -{ - triangle.index_xyz[0] = istream_read_int16_le(inputStream); - triangle.index_xyz[1] = istream_read_int16_le(inputStream); - triangle.index_xyz[2] = istream_read_int16_le(inputStream); - triangle.index_st[0] = istream_read_int16_le(inputStream); - triangle.index_st[1] = istream_read_int16_le(inputStream); - triangle.index_st[2] = istream_read_int16_le(inputStream); +void istream_read_md2Triangle( PointerInputStream& inputStream, md2Triangle_t& triangle ){ + triangle.index_xyz[0] = istream_read_int16_le( inputStream ); + triangle.index_xyz[1] = istream_read_int16_le( inputStream ); + triangle.index_xyz[2] = istream_read_int16_le( inputStream ); + triangle.index_st[0] = istream_read_int16_le( inputStream ); + triangle.index_st[1] = istream_read_int16_le( inputStream ); + triangle.index_st[2] = istream_read_int16_le( inputStream ); } typedef struct { - byte v[3]; // scaled byte to fit in frame mins/maxs - byte lightnormalindex; + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; } md2XyzNormal_t; -void istream_read_md2XyzNormal(PointerInputStream& inputStream, md2XyzNormal_t& xyz) -{ - inputStream.read(xyz.v, 3); - inputStream.read(&xyz.lightnormalindex, 1); +void istream_read_md2XyzNormal( PointerInputStream& inputStream, md2XyzNormal_t& xyz ){ + inputStream.read( xyz.v, 3 ); + inputStream.read( &xyz.lightnormalindex, 1 ); } #define MD2_XYZNORMAL_V0 0 @@ -100,21 +97,20 @@ void istream_read_md2XyzNormal(PointerInputStream& inputStream, md2XyzNormal_t& typedef struct { - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this - char name[16]; // frame name from grabbing - md2XyzNormal_t verts[1]; // variable sized + float scale[3]; // multiply byte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + md2XyzNormal_t verts[1]; // variable sized } md2Frame_t; -void istream_read_md2Frame(PointerInputStream& inputStream, md2Frame_t& frame) -{ - frame.scale[0] = istream_read_float32_le(inputStream); - frame.scale[1] = istream_read_float32_le(inputStream); - frame.scale[2] = istream_read_float32_le(inputStream); - frame.translate[0] = istream_read_float32_le(inputStream); - frame.translate[1] = istream_read_float32_le(inputStream); - frame.translate[2] = istream_read_float32_le(inputStream); - inputStream.read(reinterpret_cast(frame.name), 16); +void istream_read_md2Frame( PointerInputStream& inputStream, md2Frame_t& frame ){ + frame.scale[0] = istream_read_float32_le( inputStream ); + frame.scale[1] = istream_read_float32_le( inputStream ); + frame.scale[2] = istream_read_float32_le( inputStream ); + frame.translate[0] = istream_read_float32_le( inputStream ); + frame.translate[1] = istream_read_float32_le( inputStream ); + frame.translate[2] = istream_read_float32_le( inputStream ); + inputStream.read( reinterpret_cast( frame.name ), 16 ); } @@ -130,180 +126,171 @@ void istream_read_md2Frame(PointerInputStream& inputStream, md2Frame_t& frame) typedef struct { unsigned char ident[4]; - int version; - - int skinwidth; - int skinheight; - int framesize; // byte size of each frame - - int num_skins; - int num_xyz; - int num_st; // greater than num_xyz for seams - int num_tris; - int num_glcmds; // dwords in strip/fan command list - int num_frames; - - int ofs_skins; // each skin is a MAX_SKINNAME string - int ofs_st; // byte offset from start for md2St_t - int ofs_tris; // offset for md2triangle_t - int ofs_frames; // offset for first md2Frame_t - int ofs_glcmds; - int ofs_end; // end of file + int version; + + int skinwidth; + int skinheight; + int framesize; // byte size of each frame + + int num_skins; + int num_xyz; + int num_st; // greater than num_xyz for seams + int num_tris; + int num_glcmds; // dwords in strip/fan command list + int num_frames; + + int ofs_skins; // each skin is a MAX_SKINNAME string + int ofs_st; // byte offset from start for md2St_t + int ofs_tris; // offset for md2triangle_t + int ofs_frames; // offset for first md2Frame_t + int ofs_glcmds; + int ofs_end; // end of file } md2Header_t; -void istream_read_md2Header(PointerInputStream& inputStream, md2Header_t& header) -{ - inputStream.read(header.ident, 4); - header.version = istream_read_int32_le(inputStream); - header.skinwidth = istream_read_int32_le(inputStream); - header.skinheight = istream_read_int32_le(inputStream); - header.framesize = istream_read_int32_le(inputStream); - header.num_skins = istream_read_int32_le(inputStream); - header.num_xyz = istream_read_int32_le(inputStream); - header.num_st = istream_read_int32_le(inputStream); - header.num_tris = istream_read_int32_le(inputStream); - header.num_glcmds = istream_read_int32_le(inputStream); - header.num_frames = istream_read_int32_le(inputStream); - header.ofs_skins = istream_read_int32_le(inputStream); - header.ofs_st = istream_read_int32_le(inputStream); - header.ofs_tris = istream_read_int32_le(inputStream); - header.ofs_frames = istream_read_int32_le(inputStream); - header.ofs_glcmds = istream_read_int32_le(inputStream); - header.ofs_end = istream_read_int32_le(inputStream); +void istream_read_md2Header( PointerInputStream& inputStream, md2Header_t& header ){ + inputStream.read( header.ident, 4 ); + header.version = istream_read_int32_le( inputStream ); + header.skinwidth = istream_read_int32_le( inputStream ); + header.skinheight = istream_read_int32_le( inputStream ); + header.framesize = istream_read_int32_le( inputStream ); + header.num_skins = istream_read_int32_le( inputStream ); + header.num_xyz = istream_read_int32_le( inputStream ); + header.num_st = istream_read_int32_le( inputStream ); + header.num_tris = istream_read_int32_le( inputStream ); + header.num_glcmds = istream_read_int32_le( inputStream ); + header.num_frames = istream_read_int32_le( inputStream ); + header.ofs_skins = istream_read_int32_le( inputStream ); + header.ofs_st = istream_read_int32_le( inputStream ); + header.ofs_tris = istream_read_int32_le( inputStream ); + header.ofs_frames = istream_read_int32_le( inputStream ); + header.ofs_glcmds = istream_read_int32_le( inputStream ); + header.ofs_end = istream_read_int32_le( inputStream ); } -ArbitraryMeshVertex MD2Vertex_construct(const md2Header_t* pHeader, const md2Frame_t* pFrame, const md2XyzNormal_t* xyz, const md2St_t* st) -{ - return ArbitraryMeshVertex( - Vertex3f( - xyz->v[0] * pFrame->scale[0] + pFrame->translate[0], - xyz->v[1] * pFrame->scale[1] + pFrame->translate[1], - xyz->v[2] * pFrame->scale[2] + pFrame->translate[2] - ), - Normal3f( - g_mdl_normals[xyz->lightnormalindex][0], - g_mdl_normals[xyz->lightnormalindex][1], - g_mdl_normals[xyz->lightnormalindex][2] - ), - TexCoord2f( - (float)st->s / pHeader->skinwidth, - (float)st->t / pHeader->skinheight - ) - ); +ArbitraryMeshVertex MD2Vertex_construct( const md2Header_t* pHeader, const md2Frame_t* pFrame, const md2XyzNormal_t* xyz, const md2St_t* st ){ + return ArbitraryMeshVertex( + Vertex3f( + xyz->v[0] * pFrame->scale[0] + pFrame->translate[0], + xyz->v[1] * pFrame->scale[1] + pFrame->translate[1], + xyz->v[2] * pFrame->scale[2] + pFrame->translate[2] + ), + Normal3f( + g_mdl_normals[xyz->lightnormalindex][0], + g_mdl_normals[xyz->lightnormalindex][1], + g_mdl_normals[xyz->lightnormalindex][2] + ), + TexCoord2f( + (float)st->s / pHeader->skinwidth, + (float)st->t / pHeader->skinheight + ) + ); } -void MD2Surface_read(Model& model, const byte* buffer, ArchiveFile& file) -{ - Surface& surface = model.newSurface(); - md2Header_t header; - { - PointerInputStream inputStream(buffer); - istream_read_md2Header(inputStream, header); - } - - { - - md2Frame_t frame; - PointerInputStream frameStream(buffer + header.ofs_frames); - istream_read_md2Frame(frameStream, frame); - - - surface.indices().reserve(header.num_tris * 3); - - Array md2Xyz(header.num_xyz); - for(Array::iterator i = md2Xyz.begin(); i != md2Xyz.end(); ++i) - { - istream_read_md2XyzNormal(frameStream, *i); - } - - Array md2St(header.num_st); - PointerInputStream stStream(buffer + header.ofs_st); - for(Array::iterator i = md2St.begin(); i != md2St.end(); ++i) - { - istream_read_md2St(stStream, *i); - } - - UniqueVertexBuffer inserter(surface.vertices()); - inserter.reserve(header.num_st); - - PointerInputStream triangleStream(buffer + header.ofs_tris); - for(int i = 0; i < header.num_tris; ++i) - { - md2Triangle_t triangle; - istream_read_md2Triangle(triangleStream, triangle); - surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[0]], &md2St[triangle.index_st[0]]))); - surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[1]], &md2St[triangle.index_st[1]]))); - surface.indices().insert(inserter.insert(MD2Vertex_construct(&header, &frame, &md2Xyz[triangle.index_xyz[2]], &md2St[triangle.index_st[2]]))); - } - } - - char skinname[MD2_MAX_SKINNAME]; - char skinnameRelative[MD2_MAX_SKINNAME]; - char path[MD2_MAX_SKINNAME]; - int i = MD2_MAX_SKINNAME; - PointerInputStream inputStream(buffer + header.ofs_skins); - inputStream.read(reinterpret_cast(skinnameRelative), MD2_MAX_SKINNAME); - // relative texture path - allows moving of models in game dir structure without changing the skinpath - // e.g. used in ufo:ai - if (skinnameRelative[0] == '.') - { - strncpy(path, file.getName(), MD2_MAX_SKINNAME); - for (; i--;) +void MD2Surface_read( Model& model, const byte* buffer, ArchiveFile& file ){ + Surface& surface = model.newSurface(); + md2Header_t header; + { + PointerInputStream inputStream( buffer ); + istream_read_md2Header( inputStream, header ); + } + { - // skip filename - if (path[i] == '/' || path[i] == '\\') - break; - path[i] = '\0'; + + md2Frame_t frame; + PointerInputStream frameStream( buffer + header.ofs_frames ); + istream_read_md2Frame( frameStream, frame ); + + + surface.indices().reserve( header.num_tris * 3 ); + + Array md2Xyz( header.num_xyz ); + for ( Array::iterator i = md2Xyz.begin(); i != md2Xyz.end(); ++i ) + { + istream_read_md2XyzNormal( frameStream, *i ); + } + + Array md2St( header.num_st ); + PointerInputStream stStream( buffer + header.ofs_st ); + for ( Array::iterator i = md2St.begin(); i != md2St.end(); ++i ) + { + istream_read_md2St( stStream, *i ); + } + + UniqueVertexBuffer inserter( surface.vertices() ); + inserter.reserve( header.num_st ); + + PointerInputStream triangleStream( buffer + header.ofs_tris ); + for ( int i = 0; i < header.num_tris; ++i ) + { + md2Triangle_t triangle; + istream_read_md2Triangle( triangleStream, triangle ); + surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[0]], &md2St[triangle.index_st[0]] ) ) ); + surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[1]], &md2St[triangle.index_st[1]] ) ) ); + surface.indices().insert( inserter.insert( MD2Vertex_construct( &header, &frame, &md2Xyz[triangle.index_xyz[2]], &md2St[triangle.index_st[2]] ) ) ); + } } + + char skinname[MD2_MAX_SKINNAME]; + char skinnameRelative[MD2_MAX_SKINNAME]; + char path[MD2_MAX_SKINNAME]; + int i = MD2_MAX_SKINNAME; + PointerInputStream inputStream( buffer + header.ofs_skins ); + inputStream.read( reinterpret_cast( skinnameRelative ), MD2_MAX_SKINNAME ); + // relative texture path - allows moving of models in game dir structure without changing the skinpath + // e.g. used in ufo:ai + if ( skinnameRelative[0] == '.' ) { + strncpy( path, file.getName(), MD2_MAX_SKINNAME ); + for (; i--; ) + { + // skip filename + if ( path[i] == '/' || path[i] == '\\' ) { + break; + } + path[i] = '\0'; + } // globalErrorStream() << "modified skinname: " << path << " (path) and " << skinnameRelative << " (texture)" << "\n"; - snprintf(skinname, MD2_MAX_SKINNAME, "%s%s", path, &skinnameRelative[1]); + snprintf( skinname, MD2_MAX_SKINNAME, "%s%s", path, &skinnameRelative[1] ); // globalErrorStream() << skinname << "\n"; - } - else - { - strcpy(skinname, skinnameRelative); - } - surface.setShader(skinname); - surface.updateAABB(); + } + else + { + strcpy( skinname, skinnameRelative ); + } + surface.setShader( skinname ); + surface.updateAABB(); } -void MD2Model_read(Model& model, const byte* buffer, ArchiveFile& file) -{ - MD2Surface_read(model, buffer, file); - model.updateAABB(); +void MD2Model_read( Model& model, const byte* buffer, ArchiveFile& file ){ + MD2Surface_read( model, buffer, file ); + model.updateAABB(); } -scene::Node& MD2Model_new(const byte* buffer, ArchiveFile& file) -{ - ModelNode* modelNode = new ModelNode(); - MD2Model_read(modelNode->model(), buffer, file); - return modelNode->node(); +scene::Node& MD2Model_new( const byte* buffer, ArchiveFile& file ){ + ModelNode* modelNode = new ModelNode(); + MD2Model_read( modelNode->model(), buffer, file ); + return modelNode->node(); } -scene::Node& MD2Model_default() -{ - ModelNode* modelNode = new ModelNode(); - Model_constructNull(modelNode->model()); - return modelNode->node(); +scene::Node& MD2Model_default(){ + ModelNode* modelNode = new ModelNode(); + Model_constructNull( modelNode->model() ); + return modelNode->node(); } -scene::Node& MD2Model_fromBuffer(unsigned char* buffer, ArchiveFile& file) -{ - if (!ident_equal(buffer, MD2_IDENT)) - { - globalErrorStream() << "MD2 read error: incorrect ident\n"; - return MD2Model_default(); - } - else - { - return MD2Model_new(buffer, file); - } +scene::Node& MD2Model_fromBuffer( unsigned char* buffer, ArchiveFile& file ){ + if ( !ident_equal( buffer, MD2_IDENT ) ) { + globalErrorStream() << "MD2 read error: incorrect ident\n"; + return MD2Model_default(); + } + else + { + return MD2Model_new( buffer, file ); + } } -scene::Node& loadMD2Model(ArchiveFile& file) -{ - ScopedArchiveBuffer buffer(file); - return MD2Model_fromBuffer(buffer.buffer, file); +scene::Node& loadMD2Model( ArchiveFile& file ){ + ScopedArchiveBuffer buffer( file ); + return MD2Model_fromBuffer( buffer.buffer, file ); }