src/CSLModels.cpp
float CSLObj::FetchVertOfsFromObjFile () const
{
    float min = 0.0f, max = 0.0f;
    
    // Which file to read? Use pathOrig if defined because it could be that path doesn't exist yet
    const std::string& _path = pathOrig.empty() ? path : pathOrig;
    
    // Try opening our `.obj` file...that should actually work,
    // CSLObj only exists if the `.obj` file exists,
    // so we deal with errors but don't issue a lot of warnings here
    int lnNr = 0;
    std::ifstream fIn (TOPOSIX(_path));
    if (!fIn.good()) {
        LOG_MSG(logERR, ERR_COULD_NOT_OPEN, StripXPSysDir(_path).c_str());
        return 0.0f;
    }
    while (fIn)
    {
        std::string ln;
        safeGetline(fIn, ln);
        lnNr++;
        
        // line number 2 must define the version
        if (lnNr == 2) {
            // we can only read OBJ8 files
            if (std::stol(ln) < 800) {
                LOG_MSG(logWARN, WARN_OBJ8_ONLY_VERTOFS,
                        ln.c_str(), StripXPSysDir(_path).c_str());
                return 0.0f;
            }
        }
        
        // We try to decide really fast...obj files can be long
        // We are looking for "VT" and "VLINE", each will have at least 20 chars
        // and the first one must be 'V', the 2nd one either T or L
        if (ln.size() < 20 || ln[0] != 'V' ||
            (ln[1] != 'T' && ln[1] != 'L'))
            continue;
        
        // Chances are good we process it, so let's break it up into tokens
        std::vector<std::string> tokens = str_tokenize(ln, " \t");
        if (tokens.size() < 7 ||            // VT/VLINE must have 7 elements
            (tokens[0] != "VT" && tokens[0] != "VLINE"))
            continue;
        
        // Get and process the Y coordinate
        const float y = std::stof(tokens[2]);
        if (y < min)
            min = y;
        else if (y > max)
            max = y;
    }
    
    // return the proper VERT_OFFSET based on the Y coordinates we have read
    const float vertOfs = min < 0.0f ? -min : -max;
    LOG_MSG(logDEBUG, "Fetched VERT_OFFSET=%.1f from %s", vertOfs, StripXPSysDir(_path).c_str());
    return vertOfs;
}
// Read the obj file to calculate its vertical offset
/// @details The idea behind doing this is taken from the original libxplanemp
///          implementation, particularly
///          `XPMPMultiplayerCSLOffset.cpp: CslModelVertOffsetCalculator::findOffsetInObj8`:
///          The vertices and lines defined in the file have coordinates,
///          their outer edges define how much the aircraft would need to be
///          lifted to make its lowest part (typically the gear) appear
///          on the surfaces. So it searches for min/max values of
///          vertical (y) coordinates.
/// @note I am not sure why the original code returns `-max` if `min > 0`,
///       my understanding would be to always return `-min` and don't need `max`.
///       But I just hope that the original author knows better and I stick to it.
Read the obj file to calculate its vertical offset
Read the obj file to calculate its vertical offset
float CSLObj::FetchVertOfsFromObjFile () const
{
    float min = 0.0f, max = 0.0f;
    const std::string& _path = pathOrig.empty() ? path : pathOrig;
    int lnNr = 0;
    std::ifstream fIn (TOPOSIX(_path));
    if (!fIn.good()) {
        LOG_MSG(logERR, ERR_COULD_NOT_OPEN, StripXPSysDir(_path).c_str());
        return 0.0f;
    }
    while (fIn)
    {
        std::string ln;
        safeGetline(fIn, ln);
        lnNr++;
        if (lnNr == 2) {
            if (std::stol(ln) < 800) {
                LOG_MSG(logWARN, WARN_OBJ8_ONLY_VERTOFS,
                        ln.c_str(), StripXPSysDir(_path).c_str());
                return 0.0f;
            }
        }
        if (ln.size() < 20 || ln[0] != 'V' ||
            (ln[1] != 'T' && ln[1] != 'L'))
            continue;
        std::vector<std::string> tokens = str_tokenize(ln, " \t");
        if (tokens.size() < 7 ||            
            (tokens[0] != "VT" && tokens[0] != "VLINE"))
            continue;
        const float y = std::stof(tokens[2]);
        if (y < min)
            min = y;
        else if (y > max)
            max = y;
    }
    const float vertOfs = min < 0.0f ? -min : -max;
    LOG_MSG(logDEBUG, "Fetched VERT_OFFSET=%.1f from %s", vertOfs, StripXPSysDir(_path).c_str());
    return vertOfs;
}
float CSLObj :: FetchVertOfsFromObjFile ( ) const { float min = 0.0f , max = 0.0f ; const std :: string & _path = pathOrig . empty ( ) ? path : pathOrig ; int lnNr = 0 ; std :: ifstream fIn ( TOPOSIX ( _path ) ) ; if ( ! fIn . good ( ) ) { LOG_MSG ( logERR , ERR_COULD_NOT_OPEN , StripXPSysDir ( _path ) . c_str ( ) ) ; return 0.0f ; } while ( fIn ) { std :: string ln ; safeGetline ( fIn , ln ) ; lnNr ++ ; if ( lnNr == 2 ) { if ( std :: stol ( ln ) < 800 ) { LOG_MSG ( logWARN , WARN_OBJ8_ONLY_VERTOFS , ln . c_str ( ) , StripXPSysDir ( _path ) . c_str ( ) ) ; return 0.0f ; } } if ( ln . size ( ) < 20 || ln [ 0 ] != ' ' || ( ln [ 1 ] != ' ' && ln [ 1 ] != ' ' ) ) continue ; std :: vector < std :: string > tokens = str_tokenize ( ln , " \t " ) ; if ( tokens . size ( ) < 7 || ( tokens [ 0 ] != " " && tokens [ 0 ] != " " ) ) continue ; const float y = std :: stof ( tokens [ 2 ] ) ; if ( y < min ) min = y ; else if ( y > max ) max = y ; } const float vertOfs = min < 0.0f ? - min : - max ; LOG_MSG ( logDEBUG , " " , vertOfs , StripXPSysDir ( _path ) . c_str ( ) ) ; return vertOfs ; }
Read the obj file to calculate its vertical offset
Read the obj file to calculate its vertical offset
// Which file to read? Use pathOrig if defined because it could be that path doesn't exist yet // Try opening our `.obj` file...that should actually work, // CSLObj only exists if the `.obj` file exists, // so we deal with errors but don't issue a lot of warnings here // line number 2 must define the version // we can only read OBJ8 files // We try to decide really fast...obj files can be long // We are looking for "VT" and "VLINE", each will have at least 20 chars // and the first one must be 'V', the 2nd one either T or L // Chances are good we process it, so let's break it up into tokens // VT/VLINE must have 7 elements // Get and process the Y coordinate // return the proper VERT_OFFSET based on the Y coordinates we have read