/* ==================== idRenderModelMD5::LoadModel used for initial loads, reloadModel, and reloading the data of purged models Upon exit, the model will absolutely be valid, but possibly as a default model ==================== */ void idRenderModelMD5::LoadModel() { int version; int num; int parentNum; idToken token; idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS ); if( !purged ) { PurgeModel(); } purged = false; if( !parser.LoadFile( name ) ) { MakeDefaultModel(); return; } parser.ExpectTokenString( MD5_VERSION_STRING ); version = parser.ParseInt(); if( version != MD5_VERSION ) { parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION ); } // // skip commandline // parser.ExpectTokenString( "commandline" ); parser.ReadToken( &token ); // parse num joints parser.ExpectTokenString( "numJoints" ); num = parser.ParseInt(); joints.SetGranularity( 1 ); joints.SetNum( num ); defaultPose.SetGranularity( 1 ); defaultPose.SetNum( num ); // parse num meshes parser.ExpectTokenString( "numMeshes" ); num = parser.ParseInt(); if( num < 0 ) { parser.Error( "Invalid size: %d", num ); } meshes.SetGranularity( 1 ); meshes.SetNum( num ); // // parse joints // parser.ExpectTokenString( "joints" ); parser.ExpectTokenString( "{" ); idJointMat* poseMat = ( idJointMat* )_alloca16( joints.Num() * sizeof( poseMat[0] ) ); for( int i = 0; i < joints.Num(); i++ ) { idMD5Joint* joint = &joints[i]; idJointQuat* pose = &defaultPose[i]; ParseJoint( parser, joint, pose ); poseMat[ i ].SetRotation( pose->q.ToMat3() ); poseMat[ i ].SetTranslation( pose->t ); if( joint->parent ) { parentNum = joint->parent - joints.Ptr(); pose->q = ( poseMat[ i ].ToMat3() * poseMat[ parentNum ].ToMat3().Transpose() ).ToQuat(); pose->t = ( poseMat[ i ].ToVec3() - poseMat[ parentNum ].ToVec3() ) * poseMat[ parentNum ].ToMat3().Transpose(); } } parser.ExpectTokenString( "}" ); //----------------------------------------- // create the inverse of the base pose joints to support tech6 style deformation // of base pose vertexes, normals, and tangents. // // vertex * joints * inverseJoints == vertex when joints is the base pose // When the joints are in another pose, it gives the animated vertex position //----------------------------------------- invertedDefaultPose.SetNum( SIMD_ROUND_JOINTS( joints.Num() ) ); for( int i = 0; i < joints.Num(); i++ ) { invertedDefaultPose[i] = poseMat[i]; invertedDefaultPose[i].Invert(); } SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() ); for( int i = 0; i < meshes.Num(); i++ ) { parser.ExpectTokenString( "mesh" ); meshes[i].ParseMesh( parser, defaultPose.Num(), poseMat ); } // calculate the bounds of the model bounds.Clear(); for( int i = 0; i < meshes.Num(); i++ ) { idBounds meshBounds; meshes[i].CalculateBounds( poseMat, meshBounds ); bounds.AddBounds( meshBounds ); } // set the timestamp for reloadmodels fileSystem->ReadFile( name, NULL, &timeStamp ); common->UpdateLevelLoadPacifier(true); }
/* ==================== idRenderModelLiquid::InitFromFile ==================== */ void idRenderModelLiquid::InitFromFile( const char* fileName ) { int i, x, y; idToken token; idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS ); idList<int> tris; float size_x, size_y; float rate; name = fileName; if( !parser.LoadFile( fileName ) ) { MakeDefaultModel(); return; } size_x = scale_x * verts_x; size_y = scale_y * verts_y; while( parser.ReadToken( &token ) ) { if( !token.Icmp( "seed" ) ) { seed = parser.ParseInt(); } else if( !token.Icmp( "size_x" ) ) { size_x = parser.ParseFloat(); } else if( !token.Icmp( "size_y" ) ) { size_y = parser.ParseFloat(); } else if( !token.Icmp( "verts_x" ) ) { verts_x = parser.ParseFloat(); if( verts_x < 2 ) { parser.Warning( "Invalid # of verts. Using default model." ); MakeDefaultModel(); return; } } else if( !token.Icmp( "verts_y" ) ) { verts_y = parser.ParseFloat(); if( verts_y < 2 ) { parser.Warning( "Invalid # of verts. Using default model." ); MakeDefaultModel(); return; } } else if( !token.Icmp( "liquid_type" ) ) { liquid_type = parser.ParseInt() - 1; if( ( liquid_type < 0 ) || ( liquid_type >= LIQUID_MAX_TYPES ) ) { parser.Warning( "Invalid liquid_type. Using default model." ); MakeDefaultModel(); return; } } else if( !token.Icmp( "density" ) ) { density = parser.ParseFloat(); } else if( !token.Icmp( "drop_height" ) ) { drop_height = parser.ParseFloat(); } else if( !token.Icmp( "drop_radius" ) ) { drop_radius = parser.ParseInt(); } else if( !token.Icmp( "drop_delay" ) ) { drop_delay = SEC2MS( parser.ParseFloat() ); } else if( !token.Icmp( "shader" ) ) { parser.ReadToken( &token ); shader = declManager->FindMaterial( token ); } else if( !token.Icmp( "update_rate" ) ) { rate = parser.ParseFloat(); if( ( rate <= 0.0f ) || ( rate > 60.0f ) ) { parser.Warning( "Invalid update_rate. Must be between 0 and 60. Using default model." ); MakeDefaultModel(); return; } update_tics = 1000 / rate; } else { parser.Warning( "Unknown parameter '%s'. Using default model.", token.c_str() ); MakeDefaultModel(); return; } } scale_x = size_x / ( verts_x - 1 ); scale_y = size_y / ( verts_y - 1 ); pages.SetNum( 2 * verts_x * verts_y ); page1 = pages.Ptr(); page2 = page1 + verts_x * verts_y; verts.SetNum( verts_x * verts_y ); for( i = 0, y = 0; y < verts_y; y++ ) { for( x = 0; x < verts_x; x++, i++ ) { page1[ i ] = 0.0f; page2[ i ] = 0.0f; verts[ i ].Clear(); verts[ i ].xyz.Set( x * scale_x, y * scale_y, 0.0f ); verts[ i ].SetTexCoord( ( float ) x / ( float )( verts_x - 1 ), ( float ) - y / ( float )( verts_y - 1 ) ); } } tris.SetNum( ( verts_x - 1 ) * ( verts_y - 1 ) * 6 ); for( i = 0, y = 0; y < verts_y - 1; y++ ) { for( x = 1; x < verts_x; x++, i += 6 ) { tris[ i + 0 ] = y * verts_x + x; tris[ i + 1 ] = y * verts_x + x - 1; tris[ i + 2 ] = ( y + 1 ) * verts_x + x - 1; tris[ i + 3 ] = ( y + 1 ) * verts_x + x - 1; tris[ i + 4 ] = ( y + 1 ) * verts_x + x; tris[ i + 5 ] = y * verts_x + x; } } // build the information that will be common to all animations of this mesh: // sil edge connectivity and normal / tangent generation information deformInfo = R_BuildDeformInfo( verts.Num(), verts.Ptr(), tris.Num(), tris.Ptr(), true ); bounds.Clear(); bounds.AddPoint( idVec3( 0.0f, 0.0f, drop_height * -10.0f ) ); bounds.AddPoint( idVec3( ( verts_x - 1 ) * scale_x, ( verts_y - 1 ) * scale_y, drop_height * 10.0f ) ); // set the timestamp for reloadmodels fileSystem->ReadFile( name, NULL, &timeStamp ); Reset(); }
/* ==================== idRenderModelMD5::LoadModel used for initial loads, reloadModel, and reloading the data of purged models Upon exit, the model will absolutely be valid, but possibly as a default model ==================== */ void idRenderModelMD5::LoadModel() { int version; int i; int num; int parentNum; idToken token; idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS ); idJointQuat *pose; idMD5Joint *joint; idJointMat *poseMat3; if ( !purged ) { PurgeModel(); } purged = false; if ( !parser.LoadFile( name ) ) { MakeDefaultModel(); return; } parser.ExpectTokenString( MD5_VERSION_STRING ); version = parser.ParseInt(); if ( version != MD5_VERSION ) { parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION ); } // // skip commandline // parser.ExpectTokenString( "commandline" ); parser.ReadToken( &token ); // parse num joints parser.ExpectTokenString( "numJoints" ); num = parser.ParseInt(); joints.SetGranularity( 1 ); joints.SetNum( num ); defaultPose.SetGranularity( 1 ); defaultPose.SetNum( num ); poseMat3 = ( idJointMat * )_alloca16( num * sizeof( *poseMat3 ) ); // parse num meshes parser.ExpectTokenString( "numMeshes" ); num = parser.ParseInt(); if ( num < 0 ) { parser.Error( "Invalid size: %d", num ); } meshes.SetGranularity( 1 ); meshes.SetNum( num ); // // parse joints // parser.ExpectTokenString( "joints" ); parser.ExpectTokenString( "{" ); pose = defaultPose.Ptr(); joint = joints.Ptr(); for( i = 0; i < joints.Num(); i++, joint++, pose++ ) { ParseJoint( parser, joint, pose ); poseMat3[ i ].SetRotation( pose->q.ToMat3() ); poseMat3[ i ].SetTranslation( pose->t ); if ( joint->parent ) { parentNum = joint->parent - joints.Ptr(); pose->q = ( poseMat3[ i ].ToMat3() * poseMat3[ parentNum ].ToMat3().Transpose() ).ToQuat(); pose->t = ( poseMat3[ i ].ToVec3() - poseMat3[ parentNum ].ToVec3() ) * poseMat3[ parentNum ].ToMat3().Transpose(); } } parser.ExpectTokenString( "}" ); for( i = 0; i < meshes.Num(); i++ ) { parser.ExpectTokenString( "mesh" ); meshes[ i ].ParseMesh( parser, defaultPose.Num(), poseMat3 ); } // // calculate the bounds of the model // CalculateBounds( poseMat3 ); // set the timestamp for reloadmodels fileSystem->ReadFile( name, NULL, &timeStamp ); }