Subversion Repositories spk

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
  defines bob_dom_bob - class that can manipulate the BOB1 format and all the 
  underlying objects
*/

#ifndef BOB_DOM_BOB_INCLUDED
#define BOB_DOM_BOB_INCLUDED

#include "bob_dom_base.h"
#include "settings.h"
#include "../common/ext_utils.h"
#include "../common/ext_array.h"
#include "../common/ext_simple_list.h"
#include "../common/strutils.h"

class bob_dom_bob;

class bob_dom_bodies;
class bob_dom_body;

class bob_dom_materials;
class bob_dom_material3;
class bob_dom_material5;

class bob_dom_points;
class bob_dom_point;

class bob_dom_part;
class bob_dom_face;

class bob_point_map;

enum X2BobType
{
        bobX2,
        bobX3
};


class bob_dom_weight
{
        public:
                struct value
                {
                        static const int multiplier = 65536;
                
                        short boneIdx;
                        int boneCoefficient;
                        
                        void toFile(bob_dom_otextfilestream& os)
                        {
                                os << boneIdx << (float)(boneCoefficient / (double)multiplier);
                        }

                };
        
        private:
                
        public:
                typedef ext::list<value>::iterator iterator;
                typedef ext::list<value>::const_iterator const_iterator;
                
                bob_error_codes errorCode;
                ext::list<value> values;
                
                bob_dom_weight() { errorCode=e_noError; }
                bob_dom_weight(const bob_dom_weight& other) 
                { 
                        errorCode=other.errorCode; 
                        for(const_iterator &it=other.values.begin(); it!=other.values.end(); ++it){
                                values.push_back(*it);
                        }
                }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, int idx);
};

class bob_dom_weights : public bob_dom_section, public ext::array<bob_dom_weight*>
{
        public:
                static const int hdr_begin=BOB_SECTION_NAME_WEIGHT_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_WEIGHT_END;
                
                typedef ext::simple_list<bob_dom_weight*> WeightList;
                
                WeightList new_weights;
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, const bob_point_map *pointMap);
                
                ~bob_dom_weights()
                {
                        for(iterator &it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                        for(WeightList::iterator &it=new_weights.begin(); it!=new_weights.end(); ++it){
                                delete *it;
                        }
                }
};

class bob_dom_bones : public bob_dom_section, public ext::list<char*>
{
        public:
                static const int hdr_begin=BOB_SECTION_NAME_BONE_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_BONE_END;
                
                bool load(bob_dom_ibinaryfilestream &is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
                
                ~bob_dom_bones()
                {
                        for(iterator &it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                }
};

class bob_dom_material
{
        public:
                enum materialType
                {
                        mat1,
                        mat3,
                        mat5,
                        mat6
                };
                
                materialType type;
                short index;
                
                bob_error_codes errorCode;
                
                bob_dom_material() { index=0; }
                virtual ~bob_dom_material() { }

                virtual bool load(bob_dom_ibinaryfilestream& is) = 0;
                
                virtual bool toFile(bob_dom_obinaryfilestream& os) = 0;
                virtual bool toFile(bob_dom_otextfilestream& os) = 0;
};

class bob_dom_material1 : public bob_dom_material
{
        public:
                struct rgb
                {
                        short r, g, b;
                        rgb() { r=g=b=0; }
                };
                
                struct pair
                {
                        short value;
                        short strength;
                        pair() { value=0; strength=0; }
                };
                
                short textureID;
                rgb ambient;
                rgb diffuse;
                rgb specular;
                
                bob_dom_material1()
                {
                        type=mat1;
                        index=0; textureID=0; errorCode=e_noError;
                }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
};

inline
bob_dom_ibinaryfilestream& operator >> (bob_dom_ibinaryfilestream& is, bob_dom_material1::pair& right)
{
        is >> right.value >> right.strength;
        return is;
}

inline
bob_dom_obinaryfilestream& operator << (bob_dom_obinaryfilestream& os, bob_dom_material1::pair& right)
{
        os << right.value << right.strength;
        return os;
}

inline
bob_dom_ibinaryfilestream& operator >> (bob_dom_ibinaryfilestream& is, bob_dom_material1::rgb& r)
{
        is >> r.r >> r.g >> r.b;
        return is;
}

inline
bob_dom_obinaryfilestream& operator << (bob_dom_obinaryfilestream& os, bob_dom_material1::rgb& right)
{
        os << right.r << right.g << right.b;
        return os;
}

inline
bob_dom_otextfilestream& operator << (bob_dom_otextfilestream& os, bob_dom_material1::pair& right)
{
        int f=os.flags();
        os << noSemicolons;
        os << right.value << ';' << right.strength << "; ";
        os.flags(f);
        return os;
}

inline
bob_dom_otextfilestream& operator << (bob_dom_otextfilestream& os, bob_dom_material1::rgb& right)
{
        int f=os.flags();
        os << noSemicolons;
        os << right.r << ';' << right.g << ';' << right.b << "; ";
        os.flags(f);
        return os;
}

class bob_dom_material3 : public bob_dom_material1
{
        public:
                int transparency;
                short selfIllumination;
                pair shininess;
                bool destinationBlend;
                bool twoSided;
                bool wireframe;
                short textureValue;
                pair enviromentMap;
                pair bumpMap;
                
                typedef bob_dom_material1 base;
                
                bob_dom_material3() {
                        type=mat3;
                        transparency=0; selfIllumination=0; destinationBlend=0;
                        twoSided=0; wireframe=0; textureValue=0; 
                }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
};

class bob_dom_material5 : public bob_dom_material3
{
        private:
                
        public:
                typedef bob_dom_material3 base;
                
                pair lightMap;
                
                bob_dom_material5() { type=mat5; }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
                
};

class material6_value
{
        private:
                static char *m_stringTypes[];
                static int m_stringTypesCount;
                
        public:
                enum Type 
                {
                        typeLong=0,
                        typeBool=1,
                        typeFloat=2,
                        typeFloat4=5,
                        typeString=8
                };
                
                struct float4
                {
                        float f[4];
                };
                
                union TagValue
                {
                        bool b;
                        int i;
                        char *psz;
                        float f;
                        float4 f4;
                } val;

                Type type;
                char *name;
                
                material6_value() { val.i=0; type=typeLong; name=0; }
                material6_value(Type type) { val.i=0; this->type=type; name=0; }

                ~material6_value() { delete name; if(type==typeString) delete val.psz; }
                
                static const char * typeName(int type) { return type < m_stringTypesCount ? m_stringTypes[type] : ""; }
                const char * typeName() const { return typeName(type); }
                static int typeNameCount() { return m_stringTypesCount; }
                
                bob_error_codes load(bob_dom_ibinaryfilestream& is);
                bool toFile(bob_dom_otextfilestream& os);
                bool toFile(bob_dom_obinaryfilestream& os);
};

inline bob_dom_ibinaryfilestream& operator >> (bob_dom_ibinaryfilestream& is, material6_value::float4 &val)
{
        for(int i=0; i < 4; i++){
                is >> val.f[i];
        }
        return is;
}

inline bob_dom_obinaryfilestream& operator << (bob_dom_obinaryfilestream& os, material6_value::float4 &val)
{
        for(int i=0; i < 4; i++){
                os << val.f[i];
        }
        return os;
}

class bob_dom_material6_values : public ext::simple_list<material6_value*>
{
        public:
                typedef ext::simple_list<material6_value*> base;
                typedef base::iterator iterator;
                
        public:
                ~bob_dom_material6_values()
                {
                        for(iterator it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                }
                
                bob_error_codes load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_otextfilestream& os);
                bool toFile(bob_dom_obinaryfilestream& os);
};

class bob_dom_material6 : public bob_dom_material
{
        public:
                class Big
                {
                        public:
                                static const int flag=0x2000000;
                                
                                char *effect;
                                short technique;
                                
                                bob_dom_material6_values values;
                                
                                Big() { effect=0; technique=0; }
                                ~Big() { delete[] effect; }
                                
                                bob_error_codes load(bob_dom_ibinaryfilestream& is);
                                
                                bool toFile(bob_dom_otextfilestream& os);
                                bool toFile(bob_dom_obinaryfilestream& os);
                };
                
                class Small
                {
                        public: 
                                struct pair
                                {
                                        char *texture;
                                        short strength;
                                        
                                        pair() { texture=0; }
                                        ~pair() { delete[] texture; }
                                        
                                        pair& operator = (const pair& other) 
                                        { 
                                                strcreate(texture, other.texture); strength=other.strength; return *this; 
                                        }
                                };
                                
                                char *textureFile;
                                bob_dom_material1::rgb ambient, diffuse, specular;
                                int transparency;
                                short selfIllumination;
                                bob_dom_material1::pair shininess;
                                bool destinationBlend;
                                bool twoSided;
                                bool wireframe;
                                short textureValue;
                                pair enviromentMap;
                                pair bumpMap;
                                pair lightMap;
                                pair map4, map5;
                                
                                Small() { 
                                        textureFile=0; transparency=0; selfIllumination=0; destinationBlend=false; twoSided=false; wireframe=false;
                                        textureValue=0;
                                }
                                ~Small() 
                                { 
                                        delete[] textureFile; 
                                }
                                
                                bob_error_codes load(bob_dom_ibinaryfilestream& is, int flags);
                                
                                bool toFile(bob_dom_otextfilestream& os);
                                bool toFile(bob_dom_obinaryfilestream& os);
                };
                
        public:
#ifdef small // some fucking definition from RPC (god knows where it's included)
        #undef small
#endif
                int flags;
                Small *small;
                Big *big;
                
                bob_dom_material6() { type=mat6; flags=0; small=0; big=0; }
                ~bob_dom_material6() { delete small; delete big; }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
};

inline
bob_dom_ibinaryfilestream& operator >> (bob_dom_ibinaryfilestream& is, bob_dom_material6::Small::pair& right)
{
        is >> right.texture >> right.strength;
        return is;
}

inline
bob_dom_obinaryfilestream& operator << (bob_dom_obinaryfilestream& os, bob_dom_material6::Small::pair& right)
{
        static char *empty="";
        os << (right.texture ? right.texture : empty) << right.strength;
        return os;
}

inline
bob_dom_otextfilestream& operator << (bob_dom_otextfilestream& os, bob_dom_material6::Small::pair& right)
{
        int old=os.flags();
        os << noSemicolons << (*(right.texture)==0 ? "NULL" : right.texture) << ';' << autoSemicolons << right.strength;
        os.flags(old);
        return os;
}

class bob_dom_materials : public bob_dom_section, public ext::list<bob_dom_material*>
{
        private:
                
        public:
                static const int hdr_mat6_begin=BOB_SECTION_NAME_MAT6_BEGIN;
                static const int hdr_mat5_begin=BOB_SECTION_NAME_MAT5_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_MAT_END;
                
                bob_dom_materials() { }
                ~bob_dom_materials() 
                { 
                        for(iterator &it=begin(); it!=end(); ++it) {
                                delete *it;
                        }
                }
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
                
                bool load(bob_dom_ibinaryfilestream& is);
};

class bob_dom_point
{
        public:
                static double multiplier;
                typedef ext::list<int>::iterator iterator;
                typedef ext::list<int>::const_iterator const_iterator;
                typedef ext::pair<int, int>  pair;
                
                short type;
                ext::list<int> values;
                bob_error_codes errorCode;
                
                int x;
                int y;
                int z;
                pair textureCoords;
                
                bob_dom_point() { errorCode=e_noError; }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, int idx);
                
                bool operator ==(const bob_dom_point& right) const
                {
                        return x==right.x && y==right.y && z==right.z;
                }
};

// must be included AFTER the bob_dom_point is defined
#include "../x2bc_common/bob_point_map.h"

class bob_dom_points : public bob_dom_section
{
        public:
                static const int hdr_begin=BOB_SECTION_NAME_POINT_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_POINT_END;
                
                bob_point_map map;
                
                ext::simple_list<bob_dom_point*> new_points;
                typedef ext::simple_list<bob_dom_point*>::iterator PointIterator;
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
                
                ~bob_dom_points()
                {
                        for(PointIterator &it=new_points.begin(); it!=new_points.end(); ++it){
                                delete *it;
                        }
                }
};

class bob_x3uv
{
        public:
                int idx; // ??
                float values[6];
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_otextfilestream& os, int matIdx);
                bool toFile(bob_dom_obinaryfilestream& os);
};

class bob_x3uv_list : public ext::array<bob_x3uv*>
{
        public:
                ~bob_x3uv_list() 
                {
                        for(iterator &it=begin(); it!=end(); ++it) {
                                delete *it;
                        }
                }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_otextfilestream& os, int matIdx);
                bool toFile(bob_dom_obinaryfilestream& os);
                
                iterator search(int faceIdx)
                {
                        int min=0, mid, res, max=(int)size() - 1;
                
                        if(max==-1) return end();
                        do {
                                mid=((int)max + min) / 2;
                                res=faceIdx - at(mid)->idx;
                                if(res <= 0) max=mid - 1;
                                if(res >= 0) min=mid + 1;
                        }
                        while(min <= (int)max);
                        return faceIdx==at(mid)->idx ? (m_first + mid) : end();
                }
};

class bob_dom_face
{
        public:
                int values[4];
                bob_error_codes errorCode;
        
                bob_dom_face() { errorCode=e_noError; }
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
};

class bob_face_list : public ext::list<bob_dom_face*>, public bob_with_errors
{
        public:
                int materialIndex;
                bob_x3uv_list x3uvlist;

                bob_face_list() { materialIndex=0; }
                ~bob_face_list() 
                { 
                        for(iterator &it=begin(); it!=end(); ++it) {
                                delete *it;
                        }
                }
                
                bool load(bob_dom_ibinaryfilestream& is, bool x3data);
                bool toFile(bob_dom_obinaryfilestream& os, bool x3data);
};

class bob_dom_part_x3vals
{
        private:
                int m_values[10];
                
        public:
                bob_dom_part_x3vals() { memset(m_values, 0, sizeof(m_values)); }
                
                bool load(bob_dom_ibinaryfilestream& is);
                bool toFile(bob_dom_otextfilestream& os, bool bCommentItself);
                bool toFile(bob_dom_obinaryfilestream& os);
                
                int& operator [] (int idx) { return m_values[idx]; }
};

class bob_dom_part : public bob_with_errors, public ext::list<bob_face_list*>
{
        public:
                static const double multiplier;
                static const int x3flag=0x10000000;
                
                int flags;
                
                bob_dom_part_x3vals values;

                bob_dom_part()  { flags=0; }
                
                ~bob_dom_part()
                {
                        for(iterator &it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                }
                
                // find the appropriate face list based on material index
                bob_face_list * operator[] (int matIdx)
                {
                        for(reverse_iterator &it=rbegin(); it!=rend(); ++it){
                                if(it->materialIndex==matIdx)
                                        return *it;
                        }
                        return NULL;
                }
                
                // find or create an appropriate face list based on material index
                bob_face_list * facelist(int matIdx)
                {
                        bob_face_list *p=(*this)[matIdx];
                        if(p==NULL){
                                p=new bob_face_list();
                                push_back(p);
                                p->materialIndex=matIdx;
                        }
                        return p;
                }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, const bob_point_map *pointMap, int idx);
                
};

class bob_dom_parts : public bob_dom_section, public ext::list<bob_dom_part*>
{
        public:
                static const int hdr_begin=BOB_SECTION_NAME_PART_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_PART_END;
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, const bob_point_map *pointMap);
                
                ~bob_dom_parts()
                {
                        for(iterator &it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                }
};

class bob_dom_body : public bob_with_errors
{
        public:
                bob_dom_bones bones;
                bob_dom_points points;
                bob_dom_parts parts;
                bob_dom_weights weights;
                
                int bodySize;
                int bodyFlags;
                
                bob_dom_body() { bodySize=0; bodyFlags=0; }
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials, int idx);
};

class bob_dom_bodies : public bob_dom_section, public bob_dom_cantainer<bob_dom_body>
{
        public:
                static const int hdr_begin=BOB_SECTION_NAME_BODY_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_BODY_END;
                
                bool load(bob_dom_ibinaryfilestream& is);
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os, const Settings *settings, const bob_dom_materials *materials);
};

class bob_dom_bob : public bob_dom_section
{
        private:
                const Settings *m_settings;
                
        public:
                typedef bob_dom_bodies::iterator BodyIterator;
                
                bob_dom_info info;
                bob_dom_materials materials;
                bob_dom_bodies bodies;
                
                static const int hdr_begin=BOB_SECTION_NAME_BOB_BEGIN;
                static const int hdr_end=BOB_SECTION_NAME_BOB_END;
                
                bob_dom_bob(const Settings *settings) { m_settings=settings; }
                
                bool toFile(bob_dom_obinaryfilestream& os);
                bool toFile(bob_dom_otextfilestream& os);
                
                bool load(bob_dom_ibinaryfilestream& is);
                bool load(unsigned char *data, size_t size);
};

inline
bob_dom_otextfilestream& operator <<(bob_dom_otextfilestream& os, bob_dom_bob& right)
{
        right.toFile(os);
        return os;
}

#endif // !defined(BOB_DOM_BOB_INCLUDED)