Subversion Repositories spk

Rev

Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "bob_dom_bob.h"
//---------------------------------------------------------------------------------
// BOB file
bool bob_dom_bob::load(unsigned char *data, size_t size)
{
        int pos = 0;

        if ( data[pos++] != hdr_begin )
                return false;

        // info section
        if ( data[pos] != bob_dom_info::hdr_begin )
                return false;

        return false;
}

bool bob_dom_bob::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;        
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        if(peek(is)==bob_dom_info::hdr_begin){
                if(!info.load(is)){
                        for(ErrorIterator &it=info.errors.begin(); it!=info.errors.end(); ++it){
                                error(it->code, "info: %s", it->text);
                        }
                        return false;
                }
        }
        
        if(materials.load(is)==false){
                for(ErrorIterator &it=materials.errors.begin(); it!=materials.errors.end(); ++it){
                        error(it->code, "materials->%s", it->text);
                        return false;
                }
        }
        /*switch(m_settings->X3BOB()){
                case Settings::SwitchValue::on:
                        bobType=bobX3;
                        break;
                case Settings::SwitchValue::off:
                        bobType=bobX2;
                        break;
                default:
                        if(materials.size() && materials.front()->type >= bob_dom_material::mat6)
                                bobType=bobX3;
                        else
                                bobType=bobX2;
        }*/
        if(bodies.load(is)==false){
                for(ErrorIterator &it=bodies.errors.begin(); it!=bodies.errors.end(); ++it){
                        error(it->code, "bodies->%s", it->text);
                }
                return false;
        }
        
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
                
        return(hdr==hdr_end && !is.fail());
}
//---------------------------------------------------------------------------------
bool bob_dom_bob::toFile(bob_dom_obinaryfilestream& os)
{
        os << hdr_begin;
        info.toFile(os);
        materials.toFile(os);
        bodies.toFile(os);
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_bob::toFile(bob_dom_otextfilestream& os)
{
        info.toFile(os);
        os << endl;
        materials.toFile(os);
        if(materials.size())
                os << endl;
        bodies.toFile(os, m_settings, &materials);
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL  - object
bool bob_dom_material1::load(bob_dom_ibinaryfilestream& is)
{
        is >> index;
        is >> textureID; // int?
        is >> ambient;
        is >> diffuse;
        is >> specular;
        
        errorCode=is.fail() ? e_notEnoughData : e_noError;
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_material1::toFile(bob_dom_obinaryfilestream& os)
{
        os << index << textureID << ambient << diffuse << specular;
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material1::toFile(bob_dom_otextfilestream& os)
{
        os << noSemicolons << "MATERIAL";
        switch(type){
                case mat3:
                        os << '3';
                        break;
                case mat5:
                        os << '5';
                        break;
        }
        os << ": " << autoSemicolons;
        os << index << textureID;
        os << ambient << diffuse << specular;
        
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL 3 - object
bool bob_dom_material3::load(bob_dom_ibinaryfilestream& is)
{
        base::load(is);
        if(type > mat1){
                is >> transparency; // int?
                is >> selfIllumination;
                is >> shininess;
                short s;
                is >> s;
                destinationBlend = (s & 0x2) > 0;
                twoSided = (s & 0x10) > 0;
                wireframe = (s & 0x8) > 0;
                is >> textureValue;
                is >> enviromentMap;
                is >> bumpMap;
        }
        errorCode=is.fail() ? e_notEnoughData : e_noError;
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_material3::toFile(bob_dom_obinaryfilestream& os)
{
        base::toFile(os);
        os << transparency << selfIllumination << shininess;
        short s=0;
        if(destinationBlend) s|=0x2;
        if(twoSided) s|=0x10;
        if(wireframe) s|=0x8;
        os << s;
        os << textureValue << enviromentMap << bumpMap;
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material3::toFile(bob_dom_otextfilestream& os)
{
        base::toFile(os);
        os << autoSemicolons;
        os << transparency << selfIllumination << shininess;
        os << noSemicolons << destinationBlend << ';' << twoSided << ';' << autoSemicolons << wireframe;
        os << textureValue;
        os << enviromentMap << bumpMap;
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL5
bool bob_dom_material5::load(bob_dom_ibinaryfilestream& is)
{
        base::load(is);
        if(type > mat3)
                is >> lightMap;
        
        errorCode=is.fail() ? e_notEnoughData : e_noError;
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_material5::toFile(bob_dom_obinaryfilestream& os)
{
        base::toFile(os);
        os << lightMap;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material5::toFile(bob_dom_otextfilestream& os)
{
        base::toFile(os);
        if(type > mat3)
                os << autoSemicolons << lightMap;
        return os.good();
}
//---------------------------------------------------------------------------------
char * material6_value::m_stringTypes[]={
        "SPTYPE_LONG",
        "SPTYPE_BOOL",
        "SPTYPE_FLOAT",
        "",
        "",
        "SPTYPE_FLOAT4",
        "",
        "",
        "SPTYPE_STRING"
};

int material6_value::m_stringTypesCount=9;

bob_error_codes material6_value::load(bob_dom_ibinaryfilestream &is)
{
        is >> name;
        if(is.fail()) return e_error;
        short t;
        is >> t;
        type=(Type)t;
        
        switch(type){
                case typeBool: // no break
                case typeLong:
                        is >> val.i;
                        break;
                case typeFloat:
                        is >> val.f;
                        break;
                case typeFloat4:
                        is >> val.f4;
                        break;
                case typeString:
                        is >> val.psz;
                        break;
                default:        
                        return e_unkMaterialValueType;
        }
        return is.fail() ? e_error : e_noError;
}
//---------------------------------------------------------------------------------
bool material6_value::toFile(bob_dom_obinaryfilestream& os)
{
        os << name << (short) type;
        
        switch(type){
                case typeBool: // no break
                case typeLong:
                        os << val.i;
                        break;
                case typeFloat:
                        os << val.f;
                        break;
                case typeFloat4:
                        os << val.f4;
                        break;
                case typeString:
                        os << val.psz;
                        break;
                default:        
                        return false;
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool material6_value::toFile(bob_dom_otextfilestream& os)
{
        int old=os.flags();
        os << noSemicolons << name << ';';
        
        os << typeName() << ';';
        
        switch(type){
                case typeLong:
                        os << val.i << ';';
                        break;
                case typeBool:
                        os << val.i << ';';
                        break;
                case typeFloat:
                        os << val.f << ';';
                        break;
                case typeFloat4:
                        for(int i=0; i < 4; i++){
                                os << val.f4.f[i] << ';';
                        }
                        break;
                case typeString:
                        os << val.psz << ';';
                        break;
                default:
                        return false;
        }
        os << ' ';
        os.flags(old);
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL6_VALUES
bob_error_codes bob_dom_material6_values::load(bob_dom_ibinaryfilestream& is)
{
        short count;
        material6_value *v;
        
        bob_error_codes res;
        
        is >> count;
        for(int i=0; i < count; i++){
                v=new material6_value();
                if((res=v->load(is))!=e_noError) {
                        delete v;
                        return res;
                }
                push_back(v);
        }
        return is.fail() ? e_error : e_noError;
}
//---------------------------------------------------------------------------------
bool bob_dom_material6_values::toFile(bob_dom_obinaryfilestream& os)
{
        os << (short)size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material6_values::toFile(bob_dom_otextfilestream& os)
{
        os << (int)size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL6 - big
bob_error_codes bob_dom_material6::Big::load(bob_dom_ibinaryfilestream& is)
{
        bob_error_codes errorCode;
        
        is >> technique >> effect;
        
        errorCode=values.load(is);
        
        return errorCode;
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::Big::toFile(bob_dom_obinaryfilestream& os)
{
        os << technique << effect;
        values.toFile(os);
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::Big::toFile(bob_dom_otextfilestream& os)
{
        int old=os.flags();
        os << autoSemicolons << technique << effect;
        values.toFile(os);
        os.flags(old);
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL 6 - small
bob_error_codes bob_dom_material6::Small::load(bob_dom_ibinaryfilestream& is, int flags)
{
        is >> textureFile;
        is >> ambient >> diffuse >> specular;
        is >> transparency >> selfIllumination >> shininess;
        short s=flags;
        //is >> s;
        destinationBlend = (s & 0x2) > 0;
        twoSided = (s & 0x10) > 0;
        wireframe = (s & 0x8) > 0;
        is >> textureValue >> enviromentMap >> bumpMap >> lightMap;
        is >> map4 >> map5;
        
        return !is.fail() ? e_noError : e_notEnoughData;
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::Small::toFile(bob_dom_obinaryfilestream& os)
{
        static char *empty="";
        os << (textureFile ? textureFile : empty);
        os << ambient << diffuse << specular;
        os << transparency << selfIllumination << shininess;
        
        os << textureValue << enviromentMap << bumpMap << lightMap;
        os << map4 << map5;
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::Small::toFile(bob_dom_otextfilestream& os)
{
        os << (*textureFile==0 ? "NULL" : textureFile);
        os << ambient << diffuse << specular;
        os << transparency << selfIllumination << shininess;
        os << noSemicolons << destinationBlend << ';' << twoSided << ';' << autoSemicolons << wireframe;
        os << textureValue;
        os << enviromentMap << bumpMap << lightMap << map4 << map5;
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL 6
bool bob_dom_material6::load(bob_dom_ibinaryfilestream& is)
{
        is >> index;
        is >> flags;
        
        if(flags==Big::flag) {
                big=new Big();
                errorCode=big->load(is);
        }
        else{
                /*FILE *f=fopen("d:\\mat56.log", "a+");
                fprintf(f, "%s - flags: %d, offset 0x%x\n", is.name(), flags, is.tell());
                fclose(f);
                */
        
                small=new Small();
                errorCode=small->load(is, flags);
        }
                
        return errorCode==e_noError;
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::toFile(bob_dom_obinaryfilestream& os)
{
        bool bRes;
        
        os << index << flags;
        if(big)
                bRes=big->toFile(os);
        else
                bRes=small->toFile(os);
                
        return bRes;
}
//---------------------------------------------------------------------------------
bool bob_dom_material6::toFile(bob_dom_otextfilestream& os)
{
        int old=os.flags();
        os << noSemicolons << "MATERIAL6: " 
        << autoSemicolons << index << noSemicolons << "0x" << hex << autoSemicolons << flags << dec;
        
        if(big) 
                big->toFile(os);
        else if(small)
                small->toFile(os);
        
        os.flags(old);
        return os.good();
}
//---------------------------------------------------------------------------------
// MATERIAL - section
bool bob_dom_materials::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;
        bob_dom_material::materialType type;
        
        is >> hdr;
        switch(hdr){
                case hdr_mat5_begin:
                        type=bob_dom_material::mat5;
                        break;
                case hdr_mat6_begin:
                        type=bob_dom_material::mat6;
                        break;
                default:
                        error(e_badHeader);
                        return false;
        }
        
        int matCount;
        is >> matCount;

        bob_dom_material *m;
        for(int i=0; i < matCount; i++){
                switch(type) {
                        case bob_dom_material::mat5:
                                m=new bob_dom_material5();
                                break;
                        case bob_dom_material::mat6:
                                m=new bob_dom_material6();
                                break;
                }
                if(m->load(is)==false){
                        error(m->errorCode, "material[%d]: %s", i, bob_traslate_error(m->errorCode));
                        delete m;
                        return false;
                }
                else
                        push_back(m);
        }
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
        
        return (hdr==hdr_end && !is.fail());
}
//---------------------------------------------------------------------------------
bool bob_dom_materials::toFile(bob_dom_obinaryfilestream& os)
{
        int hdr;
        if(size() && front()->type==bob_dom_material::mat6)
                hdr=hdr_mat6_begin;
        else
                hdr=hdr_mat5_begin;
                
        os << hdr << (int)size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_materials::toFile(bob_dom_otextfilestream& os)
{
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
                os << endl;
        }
        return os.good();
}
//---------------------------------------------------------------------------------
// BODIES - section
bool bob_dom_bodies::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        short bodyCount;
        is >> bodyCount;
        
        child_type *ch;
        for(int i=0; i < bodyCount; i++){
                ch=createChild();
                if(ch->load(is)==false){
                        for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
                                error(it->code, "body[%d]->%s", i, it->text);
                        }
                        return false;
                }
        }
        
        is >> hdr;
        if(is.fail())
                error(e_notEnoughData);
                
        if(hdr!=hdr_end)
                error(e_badEndHeader);
        
        return hdr==hdr_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_bodies::toFile(bob_dom_obinaryfilestream& os)
{
        os << hdr_begin << (short)size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_bodies::toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials)
{
        bool bRes=true;
        int i=1;
        os << noSemicolons << "// beginning of bodies (" << (int)size() << ')' << endl;
        for(iterator &it=begin(); it!=end(); ++it, ++i){
                bRes&=it->toFile(os, settings, materials, i);
                os << endl;
        }
        os << "// end of bodies" << endl;
        return bRes;
}
//---------------------------------------------------------------------------------
// POINTS - section
bool bob_dom_points::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        int pointCount;
        is >> pointCount;
        
        map.create(pointCount);
        
        bob_dom_point *ch;
        for(int i=0; i < pointCount; i++){
                ch=new bob_dom_point();
                if(ch->load(is)==false){
                        error(ch->errorCode, "point[%d]: %s", i, bob_traslate_error(ch->errorCode));
                        delete ch;
                        return false;
                }
                map.addPoint(ch);
                
        }
        
        //printf("AVL Points: %d, compares: %d, average comp to find pnt: %d\n", pointCount, map.map2.m_compCount, map.map2.m_compCount / pointCount);
        
        //printf("TST: Points: %d, compares: %d, average comp to find pnt: %d\n", pointCount,map.m_compCount, map.m_compCount / pointCount);
        
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
                
        return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_points::toFile(bob_dom_obinaryfilestream& os)
{
        os << hdr_begin;
        
        if(new_points.size()){
                os << (int)new_points.size();
                for(PointIterator &it=new_points.begin(); it!=new_points.end(); ++it){
                        it->toFile(os);
                }
        }
        else{
                os << (int)map.pointsSize();
                for(bob_point_map::iterator &it=map.begin(); it!=map.end(); ++it){
                        it->toFile(os);
                }
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_points::toFile(bob_dom_otextfilestream& os)
{
        int oldf=os.flags();
        int i=0;
        os << noSemicolons << "// beginning of points (" << (int)map.uniquePointsSize() << ')' << endl << autoSemicolons;
        
        bob_dom_point *p;
        while(p=map.nextUniquePoint()){
                p->toFile(os, i++);
        }
        os << noSemicolons << "-1; -1; -1; // points end" << endl << endl;
        
        os.flags(oldf);
        return os.good();
}
//---------------------------------------------------------------------------------
// POINT - object
double bob_dom_point::multiplier=1.52587890625; // == 100000 / 65535

bool bob_dom_point::load(bob_dom_ibinaryfilestream& is)
{
        int size, v;
        
        is >> type;
        switch(type){
                case 0x1F:
                        size=11;
                        break;
                case 0x1B:
                        size=9;
                        break;
                case 0x19:
                        size=7;
                        break;
                default:
                        errorCode=e_unkPointHeader;
                        return false;
        }
        is >> x >> y >> z;
        is >> textureCoords.left >> textureCoords.right;
        
        for(int i=5; i < size; i++){
                is >> v;
                values.push_back(v);
        }
        
        if(is.fail())
                errorCode=e_notEnoughData;
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_point::toFile(bob_dom_obinaryfilestream& os)
{
        os << type << x << y << z << textureCoords.left << textureCoords.right;
        for(iterator &it=values.begin(); it!=values.end(); ++it){
                os << *it;
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_point::toFile(bob_dom_otextfilestream& os, int idx)
{
        // autoSemicolons is set by parent (points)
        int x,y,z;
        
        __asm{
                mov eax, this
                
/*              fld multiplier
                fimul [eax].x
                fistp x*/
                
                fld multiplier
                fimul [eax].y
                fistp y
                
                fld multiplier
                fimul [eax].z
                fistp z
        }
        os << x << y << z;
        
        os << noSemicolons << "// " << idx << endl << autoSemicolons;
        return os.good();
}
//---------------------------------------------------------------------------------
// X3 UV record
bool bob_x3uv::load(bob_dom_ibinaryfilestream& is)
{
        is >> idx;
        for(int i=0; i < 6; i++){
                is >> values[i];
        }
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_x3uv::toFile(bob_dom_obinaryfilestream& os)
{
        os << idx;
        for(int i=0; i < 6; i++){
                os << values[i];
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_x3uv::toFile(bob_dom_otextfilestream& os, int matIdx)
{
        int old=os.flags();
        os << autoSemicolons;
        os << matIdx << idx;
        for(int i=0; i < 6; i++){
                os << values[i];
        }
        os.flags(old);
        return os.good();
}
//---------------------------------------------------------------------------------
int compare_uv(const void *a, const void *b)
{
        const bob_x3uv *uv1=*((bob_x3uv**)a), *uv2=*((bob_x3uv**)b);
        return uv1->idx - uv2->idx;
}
//---------------------------------------------------------------------------------
// X3 uv list
bool bob_x3uv_list::load(bob_dom_ibinaryfilestream& is)
{
        int count;
        bob_x3uv *uv;
        
        is >> count;
        reserve(count);
        for(int i=0; i < count; i++){
                uv=new bob_x3uv();
                if(!uv->load(is)){
                        delete uv;
                        return false;
                }
                push_back(uv);
        }
        sort(compare_uv);
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_x3uv_list::toFile(bob_dom_obinaryfilestream& os)
{
        os << (int) size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_x3uv_list::toFile(bob_dom_otextfilestream& os, int matIdx)
{
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os, matIdx);
                os << endl;
        }
        return os.good();
}
//---------------------------------------------------------------------------------

// FACE LIST
bool bob_face_list::load(bob_dom_ibinaryfilestream& is, bool x3data)
{
        int count;
        
        is >> materialIndex >> count;
        
        for(int i=0; i < count; i++){
                bob_dom_face *face=new bob_dom_face();
                if(face->load(is)==false){
                        error(face->errorCode, "face[%d]: %s", i, bob_traslate_error(face->errorCode));
                        delete face;
                        return false;
                }
                push_back(face);
        }
        
        if(x3data && x3uvlist.load(is)==false) return false;
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_face_list::toFile(bob_dom_obinaryfilestream& os, bool x3data)
{
        os << materialIndex << (int)size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        
        if(x3data)
                x3uvlist.toFile(os);
        
        return os.good();
}
//---------------------------------------------------------------------------------
// PARTS - section PART
bool bob_dom_parts::load(bob_dom_ibinaryfilestream& is)
{
        int hdr, count;
        
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        is >> count;
        
        bob_dom_part *part;
        for(int i=0; i < count; i++){
                part=new bob_dom_part();
                if(!part->load(is)){
                        for(ErrorIterator &it=part->errors.begin(); it!=part->errors.end(); ++it){
                                error(it->severity, it->code, "part[%d]->%s", i, it->text);
                        }
                        delete part;
                        return false;
                }
                push_back(part);
        }

        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
        
        return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_parts::toFile(bob_dom_obinaryfilestream& os)
{
        os << hdr_begin << (int) size();
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        os << hdr_end;
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_parts::toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, const bob_point_map *pointMap)
{
        int i=1;
        for(iterator &it=begin(); it!=end(); ++it, ++i){
                it->toFile(os, settings, materials, pointMap, i);
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_part_x3vals::load(bob_dom_ibinaryfilestream& is)
{
        for(int i=0; i < 10; i++){
                is >> m_values[i];
        }
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_part_x3vals::toFile(bob_dom_obinaryfilestream& os)
{
        for(int i=0; i < 10; i++){
                os << m_values[i];
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_part_x3vals::toFile(bob_dom_otextfilestream& os, bool bCommentItself)
{
        int old=os.flags();
        
        os << noSemicolons;
        if(bCommentItself)
                os << "// ";
        os << "PART_VALUES_RAW: " << autoSemicolons;
        for(int i=0; i < 10; i++){
                os << m_values[i];
        }
        
        os << endl;
        
        /*os << noSemicolons << "// raw:" << endl;
        os << "// " << autoSemicolons;
        for(int i=0; i < 10; i++){
                os << m_values[i];
        }
        os << endl << */
        os << noSemicolons << "// point:" << endl;
        os << "// " << autoSemicolons;
        for(int i=0; i < 10; i++){
                os << (int)(m_values[i] / bob_dom_point::multiplier);
        }
        
        os << endl << noSemicolons << "// float:" << endl;
        static const double multiplier=1.52587890625E-05; // 1/65535
        os << "// " << autoSemicolons;
        for(int i=0; i < 10; i++){
                os << (float)(m_values[i] * multiplier);
        }
        os << endl;
        os.flags(old);
        return os.good();
}
//---------------------------------------------------------------------------------
// PARTS - object

const double bob_dom_part::multiplier=1.52587890625E-05; // == 1 / 65636

bool bob_dom_part::load(bob_dom_ibinaryfilestream& is)
{
        short count;
        
        is >> flags >> count;
        
        for(int i=0; i < count; i++){
                bob_face_list *faces=new bob_face_list();
                if(faces->load(is, (flags & x3flag) > 0)==false){
                        for(ErrorIterator &it=faces->errors.begin(); it!=faces->errors.end(); ++it){
                                error(it->severity, it->code, "face list[%d]->%s", i, it->text);
                        }
                        delete faces;
                        return false;
                }
                push_back(faces);
        }
        
        if(flags & x3flag)
                values.load(is);

        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_part::toFile(bob_dom_obinaryfilestream& os)
{
        os << flags << (short)size();
        
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os, (flags & x3flag) > 0);
        }
        
        if(flags & x3flag)
                values.toFile(os);

        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_part::toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, const bob_point_map *pointMap, int idx)
{
        bob_dom_face *part;
        const bob_dom_point *pnt;
        int line=0;
        int materialIndex;
        
        int oldf=os.flags();
        
        size_t count=0;
        for(iterator &it=begin(); it!=end(); ++it){
                count+=it->size();
        }
        
        os << noSemicolons << "// ----- part " << idx << " (" << (int)count << " faces) -----" << endl << autoSemicolons;
        for(iterator &it=begin(); it!=end(); ++it){
                materialIndex=it->materialIndex;
                
                for(bob_face_list::iterator &it2=it->begin(); it2!=it->end(); ++it2, ++line){
                        part=*it2;
                        
                        os << autoSemicolons << materialIndex;
                        for(int i=0; i < 3; i++){
                                os << pointMap->uniqueIndex(part->values[i]);
                        }
                        
                        pnt=(*pointMap)[part->values[0]];
                        if(pnt==NULL){
                                error(e_pointNotFound);
                                return false;
                        }
                        int SGBits=pnt->values.back();
                        int magic;
                        
                        /*
                                meaning of "magic" number:
                                -25: smoothing bits and UV coords
                                -17: smoothing bits and no UV coords
                                -9: no smoothing and UV coords
                                -1: no smoothing and no UV coords
                                
                                --obsolete----------------------
                                old text from Checker's sources:
                                if there are no materials used, magic is -17
                                if there are materials and last value of the first point is non zero,
                                magic is -25, otherwise it's -9
                        */
                        
                        const bob_dom_point *points_ar[3];
                        for(int i=0; i < 3; i++){
                                pnt=(*pointMap)[part->values[i]];
                                if(pnt==NULL){
                                        error(e_pointNotFound);
                                        return false;
                                }
                                points_ar[i]=pnt;
                        }
                        
                        bool bHasUV=false;
                        for(int i=0; i < 3; i++){
                                if(bHasUV=(points_ar[i]->textureCoords.left!=0 || points_ar[i]->textureCoords.right!=0))
                                        break;
                        }
                        
                        if(SGBits) {
                                if(bHasUV)
                                        magic=-25;
                                else
                                        magic=-17;
                        }
                        else{
                                if(bHasUV)
                                        magic=-9;
                                else
                                        magic=-1;
                        }
                        
                        os << magic;
                        if(SGBits!=0) os << SGBits;
                        
                        // we have uv coords so lets output them
                        if(bHasUV){
                                double u, v;
                                for(int i=0; i < 3; i++){
                                        u=points_ar[i]->textureCoords.left * multiplier;
                                        v=points_ar[i]->textureCoords.right * multiplier;
                                
                                        os << (float) u << (float) v;
                                }
                                // those are the unknown values stored in point after texture coordinates
                                // I place them after bod part definition and behind comment, so they are invisible to 
                                // bod viewer and x2
                                
                                if(settings->extraPntInfo()){
                                        bool bEmpty=true;
                                        for(int i=0; i < 3; i++){
                                                bEmpty&=(points_ar[i]->values.size() <= 1);
                                        }
                                        if(!bEmpty){
                                                os << noSemicolons << "/! ";
                                                for(int i=0; i < 3; i++){
                                                        os << "{ " << autoSemicolons;
                                                        bob_dom_point::const_iterator &last=--points_ar[i]->values.end();
                                                        double d;
                                                        for(bob_dom_point::const_iterator &it=points_ar[i]->values.begin(); it!=last; ++it){
                                                                d=*it * multiplier;
                                                                if(d==0)
                                                                        os << 0;
                                                                else
                                                                        os << (float)d;
                                                        }
                                                        os << noSemicolons << "} ";
                                                }
                                                os << "!/ " << autoSemicolons;
                                        }
                                }
                        }
                        os << noSemicolons << "// " << line << endl;
                }
        }
        
        // x3 data
        if(flags & x3flag){
                os << "// x3 part values" << endl;
                if(settings->extraX3BobInfo())
                        os << "/!" << endl;
                values.toFile(os, settings->extraX3BobInfo()==false);
                if(settings->extraX3BobInfo()) {
                        os << endl << "// secondary UVs (or whatever this is)" << endl;
                        for(iterator &it=begin(); it!=end(); ++it){
                                it->x3uvlist.toFile(os, it->materialIndex);
                        }
                        os << "!/" << endl;
                }
        }

        int bit=1;
        char str[21];
        for(int i=19; i >= 0; i--){
                str[i]=flags & bit ? '1' : '0';
                bit<<=1;
        }
        str[sizeof(str)-1]=0;
        
        os << autoSemicolons  << "-99" << str << noSemicolons << "// part " << idx << " end" << endl;
        
        os.flags(oldf);
        
        return os.good();
}
//---------------------------------------------------------------------------------
// PART - object
bool bob_dom_face::load(bob_dom_ibinaryfilestream& is)
{
        for(int i=0; i < 4; i++){
                is >> values[i];
        }
        if(is.fail()) 
                errorCode=e_notEnoughData;
                
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_face::toFile(bob_dom_obinaryfilestream& os)
{
        for(int i=0; i < 4; i++){
                os << values[i];
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_body::load(bob_dom_ibinaryfilestream& is)
{
        is >> bodySize >> bodyFlags;
        if(peek(is)==bob_dom_bones::hdr_begin){
                if(!bones.load(is)){
                        for(ErrorIterator &it=bones.errors.begin(); it!=bones.errors.end(); ++it){
                                error(it->code, "bones: %s", it->text);
                        }
                        return false;
                }
        }
        if(peek(is)==bob_dom_points::hdr_begin){
                if(points.load(is)==false){
                        for(ErrorIterator &it=points.errors.begin(); it!=points.errors.end(); ++it){
                                error(it->code, "points->%s", it->text);
                        }
                        return false;
                }
        }
        if(peek(is)==bob_dom_weights::hdr_begin){
                if(!weights.load(is)){
                        for(ErrorIterator &it=weights.errors.begin(); it!=weights.errors.end(); ++it){
                                error(it->code, "weights->%s", it->text);
                        }
                        return false;
                }
        }
        if(peek(is)==bob_dom_parts::hdr_begin){
                if(parts.load(is)==false){
                        for(ErrorIterator &it=parts.errors.begin(); it!=parts.errors.end(); ++it){
                                error(it->code, "parts->%s", it->text);
                        }
                        return false;
                }
        }
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_body::toFile(bob_dom_obinaryfilestream& os)
{
        os << bodySize << bodyFlags;
        
        bones.toFile(os);
        points.toFile(os);
        weights.toFile(os);
        parts.toFile(os);
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_body::toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, int idx)
{
        os << "// beginning of body " << idx << endl;
        os << autoSemicolons << bodySize << endl << endl;
        
        bones.toFile(os);
        
        points.toFile(os);
        
        weights.toFile(os, &points.map);
        
        parts.toFile(os, settings, materials, &points.map);
        
        char str[17]; int bit=1;
        for(int i=15; i >= 0; i--){
                str[i]=bodyFlags & bit ? '1' : '0';
                bit<<=1;
        }
        str[sizeof(str)-1]=0;
        
        os << "-99" << str << noSemicolons << "// body " << idx << " end" << endl;
        
        return os.good();
}
//---------------------------------------------------------------------------------
// BONES
bool bob_dom_bones::load(bob_dom_ibinaryfilestream& is)
{
        int hdr, count;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        is >> count;
        char *name;
        for(int i=0; i < count; i++){
                is >> name;
                if(name==0){
                        error(e_notEnoughData);
                        delete[] name;
                        return false;
                }
                push_back(name);
        }
        is >> hdr;
        if(hdr!=hdr_end){
                error(e_badEndHeader);
                return false;
        }
        return true;
}
//---------------------------------------------------------------------------------
bool bob_dom_bones::toFile(bob_dom_obinaryfilestream& os)
{
        if(size()==0) return true;
        
        os << hdr_begin << (int) size();
        for(iterator &it=begin(); it!=end(); ++it){
                os << *it;
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_bones::toFile(bob_dom_otextfilestream& os)
{
        if(size()==0) return true;
        os << noSemicolons << "BONES: " << autoSemicolons << (int)size() << endl;
        for(iterator &it=begin(); it!=end(); ++it){
                os << *it << endl;
        }
        os << endl;
        return os.good();
}
//---------------------------------------------------------------------------------
// WEIGHTS - section
bool bob_dom_weights::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        int count;
        is >> count;
        resize(count);
        
        bob_dom_weight *ch;
        for(int i=0; i < count; i++){
                ch=new bob_dom_weight();
                if(!ch->load(is)){
                        error(ch->errorCode, "weight[%d]: %s", i, bob_traslate_error(ch->errorCode));
                        delete ch;
                        return false;
                }
                (*this)[i]=ch;
        }
        is >> hdr;
        if(hdr!=hdr_end){
                error(e_badEndHeader);
                return false;
        }
        return true;
}
//---------------------------------------------------------------------------------
bool bob_dom_weights::toFile(bob_dom_obinaryfilestream& os)
{
        if(new_weights.size()==0 && size()==0) return true;
        
        os << hdr_begin;
        if(new_weights.size()){
                os << (int)new_weights.size();
                for(WeightList::iterator &it=new_weights.begin(); it!=new_weights.end(); ++it){
                        it->toFile(os);
                }
        }
        else{
                os << (int)size();
                for(iterator &it=begin(); it!=end(); ++it){
                        it->toFile(os);
                }
        }
        
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_weights::toFile(bob_dom_otextfilestream& os, const bob_point_map *pointMap)
{
        if(size()==0) return true;
        os << noSemicolons << "WEIGHTS " << autoSemicolons << (int) pointMap->uniquePointsSize() << endl;
        int i=0;
        for(bob_point_map::const_index_iterator &it=pointMap->indexBegin(); it!=pointMap->indexEnd(); ++it){
                (*this)[*it]->toFile(os, i++);
        }
        os << autoSemicolons << "-1" << endl << endl;
        return os.good();
}
//---------------------------------------------------------------------------------
// WEIGHT - object
bool bob_dom_weight::load(bob_dom_ibinaryfilestream& is)
{
        short count;
        value v;
        
        is >> count;
        
        for(int i=0; i < count; i++){
                is >> v.boneIdx >> v.boneCoefficient;
                values.push_back(v);
        }
        
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_weight::toFile(bob_dom_obinaryfilestream& os)
{       
        os << (short) values.size();
        
        value v;
        for(iterator &it=values.begin(); it!=values.end(); ++it){
                v=*it;
                os << v.boneIdx << v.boneCoefficient;
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_weight::toFile(bob_dom_otextfilestream& os, int idx)
{
        os << autoSemicolons;
        for(iterator &it=values.begin(); it!=values.end(); ++it){
                (*it).toFile(os);
        }
        os << noSemicolons << "-1; // " << idx << endl;
        return os.good();
}
//---------------------------------------------------------------------------------