X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=plugins%2Fmd3model%2Fmd5.cpp;h=69719051c588e568cbafad6b86edebc8dc41eed1;hp=9ce15a76ff95fee4858c2d13a53db1535f653046;hb=62d99f889c0e98be65f779d3983109c84ce58cec;hpb=107765f0e4b543dfc346851ee5b4605cc17eb1c6 diff --git a/plugins/md3model/md5.cpp b/plugins/md3model/md5.cpp index 9ce15a76..69719051 100644 --- a/plugins/md3model/md5.cpp +++ b/plugins/md3model/md5.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 "md5.h" @@ -29,66 +29,59 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "model.h" -#define MD5_RETURN_FALSE_IF_FAIL(expression) if(!(expression)) { globalErrorStream() << "md5 parse failed: " #expression "\n"; return false; } else +#define MD5_RETURN_FALSE_IF_FAIL( expression ) if ( !( expression ) ) { globalErrorStream() << "md5 parse failed: " # expression "\n"; return false; } else -bool MD5_parseToken(Tokeniser& tokeniser, const char* string) -{ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL(token != 0); - return string_equal(token, string); +bool MD5_parseToken( Tokeniser& tokeniser, const char* string ){ + const char* token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL( token != 0 ); + return string_equal( token, string ); } -bool MD5_parseFloat(Tokeniser& tokeniser, float& f) -{ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL(token != 0); - return string_parse_float(token, f); +bool MD5_parseFloat( Tokeniser& tokeniser, float& f ){ + const char* token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL( token != 0 ); + return string_parse_float( token, f ); } -bool MD5_parseString(Tokeniser& tokeniser, const char*& s) -{ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL(token != 0); - s = token; - return true; +bool MD5_parseString( Tokeniser& tokeniser, const char*& s ){ + const char* token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL( token != 0 ); + s = token; + return true; } -bool MD5_parseInteger(Tokeniser& tokeniser, int& i) -{ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL(token != 0); - return string_parse_int(token, i); +bool MD5_parseInteger( Tokeniser& tokeniser, int& i ){ + const char* token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL( token != 0 ); + return string_parse_int( token, i ); } -bool MD5_parseSize(Tokeniser& tokeniser, std::size_t& i) -{ - const char* token = tokeniser.getToken(); - MD5_RETURN_FALSE_IF_FAIL(token != 0); - return string_parse_size(token, i); +bool MD5_parseSize( Tokeniser& tokeniser, std::size_t& i ){ + const char* token = tokeniser.getToken(); + MD5_RETURN_FALSE_IF_FAIL( token != 0 ); + return string_parse_size( token, i ); } -bool MD5_parseVector3(Tokeniser& tokeniser, Vector3& v) -{ - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "(")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.x())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.y())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, v.z())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")")); - return true; +bool MD5_parseVector3( Tokeniser& tokeniser, Vector3& v ){ + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.x() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.y() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, v.z() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) ); + return true; } template -inline Element float_squared(const Element& f) -{ - return f * f; +inline Element float_squared( const Element& f ){ + return f * f; } class MD5Joint { public: - int parent; - Vector3 position; - Vector4 rotation; +int parent; +Vector3 position; +Vector4 rotation; }; typedef Array MD5Joints; @@ -96,11 +89,11 @@ typedef Array MD5Joints; class MD5Vert { public: - std::size_t index; - float u; - float v; - std::size_t weight_index; - std::size_t weight_count; +std::size_t index; +float u; +float v; +std::size_t weight_index; +std::size_t weight_count; }; typedef Array MD5Verts; @@ -108,10 +101,10 @@ typedef Array MD5Verts; class MD5Tri { public: - std::size_t index; - std::size_t a; - std::size_t b; - std::size_t c; +std::size_t index; +std::size_t a; +std::size_t b; +std::size_t c; }; typedef Array MD5Tris; @@ -119,10 +112,10 @@ typedef Array MD5Tris; class MD5Weight { public: - std::size_t index; - std::size_t joint; - float t; - Vector3 v; +std::size_t index; +std::size_t joint; +float t; +Vector3 v; }; typedef Array MD5Weights; @@ -133,322 +126,314 @@ typedef Array MD5Components; class MD5Frame { public: - MD5Components m_components; +MD5Components m_components; }; typedef Array MD5Weights; -bool MD5_parseVersion(Tokeniser& tokeniser) -{ - { - const char* versionKey = tokeniser.getToken(); - if(versionKey == 0 || !string_equal(versionKey, "MD5Version")) - { - globalErrorStream() << "not a valid md5 file\n"; - return false; - } - } - { - const char* versionValue = tokeniser.getToken(); - if(versionValue == 0 || !string_equal(versionValue, "10")) - { - globalErrorStream() << "only md5 version 10 supported\n"; - return false; - } - } - - return true; +bool MD5_parseVersion( Tokeniser& tokeniser ){ + { + const char* versionKey = tokeniser.getToken(); + if ( versionKey == 0 || !string_equal( versionKey, "MD5Version" ) ) { + globalErrorStream() << "not a valid md5 file\n"; + return false; + } + } + { + const char* versionValue = tokeniser.getToken(); + if ( versionValue == 0 || !string_equal( versionValue, "10" ) ) { + globalErrorStream() << "only md5 version 10 supported\n"; + return false; + } + } + + return true; } -bool MD5Anim_parse(Tokeniser& tokeniser) -{ - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline")); - const char* commandline; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numFrames")); - std::size_t numFrames; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numFrames)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints")); - std::size_t numJoints; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frameRate")); - std::size_t frameRate; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, frameRate)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numAnimatedComponents")); - std::size_t numAnimatedComponents; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numAnimatedComponents)); - tokeniser.nextLine(); - - // parse heirarchy - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "hierarchy")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(std::size_t i = 0; i < numJoints; ++i) - { - const char* name; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, name)); - int parent; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, parent)); - std::size_t flags; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, flags)); - std::size_t index; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, index)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - - // parse bounds - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "bounds")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(std::size_t i = 0; i < numFrames; ++i) - { - Vector3 mins; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, mins)); - Vector3 maxs; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, maxs)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - - // parse baseframe - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "baseframe")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(std::size_t i = 0; i < numJoints; ++i) - { - Vector3 position; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, position)); - Vector3 rotation; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, rotation)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - - // parse frames - for(std::size_t i = 0; i < numFrames; ++i) - { - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "frame")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(std::size_t i = 0; i < numAnimatedComponents; ++i) - { - float component; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, component)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - } - - return true; +bool MD5Anim_parse( Tokeniser& tokeniser ){ + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) ); + const char* commandline; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numFrames" ) ); + std::size_t numFrames; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numFrames ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) ); + std::size_t numJoints; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frameRate" ) ); + std::size_t frameRate; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, frameRate ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numAnimatedComponents" ) ); + std::size_t numAnimatedComponents; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numAnimatedComponents ) ); + tokeniser.nextLine(); + + // parse heirarchy + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "hierarchy" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for ( std::size_t i = 0; i < numJoints; ++i ) + { + const char* name; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, name ) ); + int parent; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, parent ) ); + std::size_t flags; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, flags ) ); + std::size_t index; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, index ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + + // parse bounds + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "bounds" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for ( std::size_t i = 0; i < numFrames; ++i ) + { + Vector3 mins; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, mins ) ); + Vector3 maxs; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, maxs ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + + // parse baseframe + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "baseframe" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for ( std::size_t i = 0; i < numJoints; ++i ) + { + Vector3 position; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, position ) ); + Vector3 rotation; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, rotation ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + + // parse frames + for ( std::size_t i = 0; i < numFrames; ++i ) + { + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "frame" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for ( std::size_t i = 0; i < numAnimatedComponents; ++i ) + { + float component; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, component ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + } + + return true; } -bool MD5Model_parse(Model& model, Tokeniser& tokeniser) -{ - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVersion(tokeniser)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "commandline")); - const char* commandline; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, commandline)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numJoints")); - std::size_t numJoints; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numJoints)); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numMeshes")); - std::size_t numMeshes; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numMeshes)); - tokeniser.nextLine(); - - MD5Joints joints(numJoints); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "joints")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i) - { - const char* jointName; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, jointName)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseInteger(tokeniser, (*i).parent)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*i).position)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, vector4_to_vector3((*i).rotation))); - (*i).rotation.w() = -static_cast(sqrt(1.0f - (float_squared((*i).rotation.x()) + float_squared((*i).rotation.y()) + float_squared((*i).rotation.z())))); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - - for(std::size_t i = 0; i < numMeshes; ++i) - { - Surface& surface = model.newSurface(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "mesh")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "shader")); - const char* shader; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseString(tokeniser, shader)); - surface.setShader(shader); - tokeniser.nextLine(); - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numverts")); - std::size_t numVerts; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numVerts)); - tokeniser.nextLine(); - - MD5Verts verts(numVerts); - - for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j) - { - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "vert")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); - MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - verts.begin())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "(")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).u)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).v)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, ")")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_index)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).weight_count)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numtris")); - std::size_t numTris; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numTris)); - tokeniser.nextLine(); - - MD5Tris tris(numTris); - - for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) - { - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "tri")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); - MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - tris.begin())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).a)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).b)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).c)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "numweights")); - std::size_t numWeights; - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, numWeights)); - tokeniser.nextLine(); - - MD5Weights weights(numWeights); - - for(MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j) - { - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "weight")); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).index)); - MD5_RETURN_FALSE_IF_FAIL((*j).index == std::size_t(j - weights.begin())); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseSize(tokeniser, (*j).joint)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseFloat(tokeniser, (*j).t)); - MD5_RETURN_FALSE_IF_FAIL(MD5_parseVector3(tokeniser, (*j).v)); - tokeniser.nextLine(); - } - - MD5_RETURN_FALSE_IF_FAIL(MD5_parseToken(tokeniser, "}")); - tokeniser.nextLine(); - - for(MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j) - { - MD5Vert& vert = (*j); - - Vector3 skinned(0, 0, 0); - for(std::size_t k = 0; k != vert.weight_count; ++k) - { - MD5Weight& weight = weights[vert.weight_index + k]; - MD5Joint& joint = joints[weight.joint]; - - skinned += (quaternion_transformed_point(joint.rotation, weight.v) + joint.position) * weight.t; - } - - surface.vertices().push_back(ArbitraryMeshVertex(vertex3f_for_vector3(skinned), Normal3f(0, 0, 0), TexCoord2f(vert.u, vert.v))); - } - - for(MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j) - { - MD5Tri& tri = (*j); - surface.indices().insert(RenderIndex(tri.a)); - surface.indices().insert(RenderIndex(tri.b)); - surface.indices().insert(RenderIndex(tri.c)); - } - - for(Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3) - { - ArbitraryMeshVertex& a = surface.vertices()[*(j + 0)]; - ArbitraryMeshVertex& b = surface.vertices()[*(j + 1)]; - ArbitraryMeshVertex& c = surface.vertices()[*(j + 2)]; +bool MD5Model_parse( Model& model, Tokeniser& tokeniser ){ + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVersion( tokeniser ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "commandline" ) ); + const char* commandline; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, commandline ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numJoints" ) ); + std::size_t numJoints; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numJoints ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numMeshes" ) ); + std::size_t numMeshes; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numMeshes ) ); + tokeniser.nextLine(); + + MD5Joints joints( numJoints ); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "joints" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for ( MD5Joints::iterator i = joints.begin(); i != joints.end(); ++i ) + { + const char* jointName; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, jointName ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseInteger( tokeniser, ( *i ).parent ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *i ).position ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, vector4_to_vector3( ( *i ).rotation ) ) ); + ( *i ).rotation.w() = -static_cast( sqrt( 1.0f - ( float_squared( ( *i ).rotation.x() ) + float_squared( ( *i ).rotation.y() ) + float_squared( ( *i ).rotation.z() ) ) ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + + for ( std::size_t i = 0; i < numMeshes; ++i ) + { + Surface& surface = model.newSurface(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "mesh" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "shader" ) ); + const char* shader; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseString( tokeniser, shader ) ); + surface.setShader( shader ); + tokeniser.nextLine(); + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numverts" ) ); + std::size_t numVerts; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numVerts ) ); + tokeniser.nextLine(); + + MD5Verts verts( numVerts ); + + for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j ) + { + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "vert" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); + MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - verts.begin() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "(" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).u ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).v ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, ")" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_index ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).weight_count ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numtris" ) ); + std::size_t numTris; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numTris ) ); + tokeniser.nextLine(); + + MD5Tris tris( numTris ); + + for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j ) + { + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "tri" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); + MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - tris.begin() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).a ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).b ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).c ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "numweights" ) ); + std::size_t numWeights; + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, numWeights ) ); + tokeniser.nextLine(); + + MD5Weights weights( numWeights ); + + for ( MD5Weights::iterator j = weights.begin(); j != weights.end(); ++j ) + { + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "weight" ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).index ) ); + MD5_RETURN_FALSE_IF_FAIL( ( *j ).index == std::size_t( j - weights.begin() ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseSize( tokeniser, ( *j ).joint ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseFloat( tokeniser, ( *j ).t ) ); + MD5_RETURN_FALSE_IF_FAIL( MD5_parseVector3( tokeniser, ( *j ).v ) ); + tokeniser.nextLine(); + } + + MD5_RETURN_FALSE_IF_FAIL( MD5_parseToken( tokeniser, "}" ) ); + tokeniser.nextLine(); + + for ( MD5Verts::iterator j = verts.begin(); j != verts.end(); ++j ) + { + MD5Vert& vert = ( *j ); + + Vector3 skinned( 0, 0, 0 ); + for ( std::size_t k = 0; k != vert.weight_count; ++k ) + { + MD5Weight& weight = weights[vert.weight_index + k]; + MD5Joint& joint = joints[weight.joint]; + + skinned += ( quaternion_transformed_point( joint.rotation, weight.v ) + joint.position ) * weight.t; + } + + surface.vertices().push_back( ArbitraryMeshVertex( vertex3f_for_vector3( skinned ), Normal3f( 0, 0, 0 ), TexCoord2f( vert.u, vert.v ) ) ); + } + + for ( MD5Tris::iterator j = tris.begin(); j != tris.end(); ++j ) + { + MD5Tri& tri = ( *j ); + surface.indices().insert( RenderIndex( tri.a ) ); + surface.indices().insert( RenderIndex( tri.b ) ); + surface.indices().insert( RenderIndex( tri.c ) ); + } + + for ( Surface::indices_t::iterator j = surface.indices().begin(); j != surface.indices().end(); j += 3 ) + { + ArbitraryMeshVertex& a = surface.vertices()[*( j + 0 )]; + ArbitraryMeshVertex& b = surface.vertices()[*( j + 1 )]; + ArbitraryMeshVertex& c = surface.vertices()[*( j + 2 )]; Vector3 weightedNormal( - vector3_cross( - reinterpret_cast(c.vertex) - reinterpret_cast(a.vertex), - reinterpret_cast(b.vertex) - reinterpret_cast(a.vertex) - ) - ); - reinterpret_cast(a.normal) += weightedNormal; - reinterpret_cast(b.normal) += weightedNormal; - reinterpret_cast(c.normal) += weightedNormal; - } - - for(Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j) - { - vector3_normalise(reinterpret_cast((*j).normal)); - } - - surface.updateAABB(); - } - - model.updateAABB(); - - return true; + vector3_cross( + reinterpret_cast( c.vertex ) - reinterpret_cast( a.vertex ), + reinterpret_cast( b.vertex ) - reinterpret_cast( a.vertex ) + ) + ); + reinterpret_cast( a.normal ) += weightedNormal; + reinterpret_cast( b.normal ) += weightedNormal; + reinterpret_cast( c.normal ) += weightedNormal; + } + + for ( Surface::vertices_t::iterator j = surface.vertices().begin(); j != surface.vertices().end(); ++j ) + { + vector3_normalise( reinterpret_cast( ( *j ).normal ) ); + } + + surface.updateAABB(); + } + + model.updateAABB(); + + return true; } -void MD5Model_construct(Model& model, TextInputStream& inputStream) -{ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(inputStream); - MD5Model_parse(model, tokeniser); - tokeniser.release(); +void MD5Model_construct( Model& model, TextInputStream& inputStream ){ + Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( inputStream ); + MD5Model_parse( model, tokeniser ); + tokeniser.release(); } -scene::Node& MD5Model_new(TextInputStream& inputStream) -{ - ModelNode* modelNode = new ModelNode(); - MD5Model_construct(modelNode->model(), inputStream); - return modelNode->node(); +scene::Node& MD5Model_new( TextInputStream& inputStream ){ + ModelNode* modelNode = new ModelNode(); + MD5Model_construct( modelNode->model(), inputStream ); + return modelNode->node(); } -scene::Node& loadMD5Model(ArchiveFile& file) -{ - BinaryToTextInputStream inputStream(file.getInputStream()); - return MD5Model_new(inputStream); +scene::Node& loadMD5Model( ArchiveFile& file ){ + BinaryToTextInputStream inputStream( file.getInputStream() ); + return MD5Model_new( inputStream ); }