X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=plugins%2Fmd3model%2Fmd5.cpp;fp=plugins%2Fmd3model%2Fmd5.cpp;h=0a548f44384fec1fadc9fa37a53d8d7e023a21c6;hp=e1c5de56d23f0ea0e4ec149a6c62115d9a0992b8;hb=9dfae1c9b270ee369c6362903a9205b30751b95f;hpb=0a6d5683b0cfa1a0bd7ef64bada105dbe4ddd6e1 diff --git a/plugins/md3model/md5.cpp b/plugins/md3model/md5.cpp index e1c5de56..0a548f44 100644 --- a/plugins/md3model/md5.cpp +++ b/plugins/md3model/md5.cpp @@ -31,91 +31,94 @@ #define MD5_RETURN_FALSE_IF_FAIL(expression) do { if (!(expression)) { globalErrorStream() << "md5 parse failed: " #expression "\n"; return false; } } while (0) -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 -{ +class MD5Joint { public: -int parent; -Vector3 position; -Vector4 rotation; + int parent; + Vector3 position; + Vector4 rotation; }; typedef Array MD5Joints; -class MD5Vert -{ +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; -class MD5Tri -{ +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; -class MD5Weight -{ +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; @@ -123,317 +126,312 @@ typedef Array MD5Weights; typedef float MD5Component; typedef Array MD5Components; -class MD5Frame -{ +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 )]; - 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; +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; } -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); }