Subversion Repositories spk

Rev

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

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

#ifndef BOB_BOB_INCLUDED
#define BOB_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"
#include "../common/ptr_list.h"

#include "conversion.h"

class bob_dom_bob;

class bob_bodies;
class bob_body;

class bob_materials;
class bob_material3;
class bob_material5;

class bob_points;
class bob_vertex;

class bob_part;
class bob_face;

class bob_point_map;

enum X2BobType
{
        bobX2,
        bobX3
};


class bob_weight
{
        public:
                struct value
                {
                        static const int MULTIPLIER = 65536;

                        short boneIdx;
                        int boneCoefficient;

                        void toFile(otextfilestream& os)
                        {
                                os << boneIdx << (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_weight() { errorCode=e_noError; }
                bob_weight(const bob_weight& other)
                {
                        errorCode=other.errorCode;
                        for(const_iterator &it=other.values.begin(); it!=other.values.end(); ++it){
                                values.push_back(*it);
                        }
                }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, int idx);
};

class bob_weights : public bob_section, public ptr_list<ext::array<bob_weight*> >
{
        public:
                static const int HDR_BEGIN = BOB_SECTION_NAME_WEIGHT_BEGIN;
                static const int HDR_END = BOB_SECTION_NAME_WEIGHT_END;

                typedef ptr_list<ext::simple_list<bob_weight*> > WeightList;

                WeightList new_weights;

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, const bob_point_map *pointMap);
};

class bob_bones : public bob_section, public ptr_list<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(ibinaryfilestream &is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os);

};

class bob_material
{
        public:
                enum materialType
                {
                        mat1,
                        mat3,
                        mat5,
                        mat6
                };

                materialType type;
                short index;

                bob_error_codes errorCode;

                bob_material() { index=0; }
                virtual ~bob_material() { }

                virtual bool load(ibinaryfilestream& is) = 0;

                virtual bool toFile(obinaryfilestream& os) = 0;
                virtual bool toFile(otextfilestream& os) = 0;
};

class bob_material1 : public bob_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_material1()
                {
                        type=mat1;
                        index=0; textureID=0; errorCode=e_noError;
                }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os);
};

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

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

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

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

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

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

class bob_material3 : public bob_material1
{
        public:
                int transparency;
                short selfIllumination;
                pair shininess;
                bool destinationBlend;
                bool twoSided;
                bool wireframe;
                short textureValue;
                pair enviromentMap;
                pair bumpMap;

                typedef bob_material1 base;

                bob_material3() {
                        type=mat3;
                        transparency=0; selfIllumination=0; destinationBlend=0;
                        twoSided=0; wireframe=0; textureValue=0;
                }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os);
};

class bob_material5 : public bob_material3
{
        private:

        public:
                typedef bob_material3 base;

                pair lightMap;

                bob_material5() { type=mat5; }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(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(ibinaryfilestream& is);
                bool toFile(otextfilestream& os);
                bool toFile(obinaryfilestream& os);
};

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

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

class bob_material6_values : public ptr_list<ext::simple_list<material6_value*> >
{
        public:
                typedef ext::simple_list<material6_value*> base;
                typedef base::iterator iterator;

        public:
                bob_error_codes load(ibinaryfilestream& is);

                bool toFile(otextfilestream& os);
                bool toFile(obinaryfilestream& os);
};

class bob_material6 : public bob_material
{
        public:
                class Big
                {
                        public:
                                static const int flag=0x2000000;

                                char *effect;
                                short technique;

                                bob_material6_values values;

                                Big() { effect=0; technique=0; }
                                ~Big() { delete[] effect; }

                                bob_error_codes load(ibinaryfilestream& is);

                                bool toFile(otextfilestream& os);
                                bool toFile(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_material1::rgb ambient, diffuse, specular;
                                int transparency;
                                short selfIllumination;
                                bob_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(ibinaryfilestream& is, int flags);

                                bool toFile(otextfilestream& os);
                                bool toFile(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_material6() { type=mat6; flags=0; small=0; big=0; }
                ~bob_material6() { delete small; delete big; }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os);
};

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

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

inline
otextfilestream& operator << (otextfilestream& os, bob_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_materials : public bob_section, public ptr_list<ext::list<bob_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;

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os);

                bool load(ibinaryfilestream& is);
};

#include "geometry_bob.h"

class bob_vertex : public vertex
{
        public:
                typedef point2d<double> uv_coord;

                static const int FLAG_DEFAULT = 0x19;
                static const int FLAG_UV = 2;
                static const int FLAG_WEIRD_STUFF = 4;

        private:

        public:
                short flags;
                bob_error_codes errorCode;
                uv_coord textureCoords;
                point2d<double> weirdCoords;
                int sgbits;
                normal_vector normalVector;
                normal_vector tangentVector;

        public:
                bob_vertex() { errorCode=e_noError; flags=0; }
                bob_vertex(int x, int y, int z)
                        : vertex(x,y,z)
                {
                        errorCode=e_noError;
                        flags=0;
                }

                bool hasTextureCoords() const { return (flags & FLAG_UV) > 0; }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, int idx);

                void getBodCoords(int *coords)
                {
                        coords[0]=conversion::vertex_bob2bod(x);
                        coords[1]=conversion::vertex_bob2bod(y);
                        coords[2]=conversion::vertex_bob2bod(z);
                }
};

// must be included AFTER the bob_vertex is defined

#include "../x2bc_common/bob_point_map.h"

class bob_vertices : public bob_section
{
        public:
                static const int HDR_BEGIN = BOB_SECTION_NAME_POINT_BEGIN;
                static const int HDR_END = BOB_SECTION_NAME_POINT_END;

                typedef ptr_list<ext::array<bob_vertex*> > VertexArray;
                typedef VertexArray::iterator VertexIterator;

        public:
                bob_point_map map;
                VertexArray new_vertices;

        private:
                bool outputRaw(otextfilestream& os);
                bool outputBOD(otextfilestream& os);

        public:
                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, const Settings& settings);
};

class bob_x3vertex_data_record
{
        public:
                int pointIndex; // index of BOB point
                vector tangent;
                vector unk;

                bool load(ibinaryfilestream& is);
                bool toFile(obinaryfilestream& os);
};

class bob_x3vertex_data : public ptr_list<ext::array<bob_x3vertex_data_record*> >
{
        public:
                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);

                iterator search(int pointIndex)
                {
                        int min=0, mid, res, max=(int)size() - 1;

                        if(max==-1) return end();
                        do {
                                mid=(max + min) / 2;
                                res=pointIndex - at(mid)->pointIndex;
                                if(res <= 0) max=mid - 1;
                                if(res >= 0) min=mid + 1;
                        }
                        while(min <= (int)max);
                        return pointIndex==at(mid)->pointIndex ? (m_first + mid) : end();
                }
                
                const_iterator search(int pointIndex) const
                {
                        int min=0, mid, res, max=(int)size() - 1;

                        if(max==-1) return end();
                        do {
                                mid=(max + min) / 2;
                                res=pointIndex - at(mid)->pointIndex;
                                if(res <= 0) max=mid - 1;
                                if(res >= 0) min=mid + 1;
                        }
                        while(min <= (int)max);
                        return pointIndex==at(mid)->pointIndex ? (m_first + mid) : end();
                }
};

class bob_face
{
        public:
                int values[3];
                int flags;
                bob_error_codes errorCode;

                bob_face() { errorCode=e_noError; }
                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
};

class bob_face_list : public ptr_list<ext::list<bob_face*> >, public bob_with_errors
{
        private:
                bool saveVertexTangents(obinaryfilestream& os, const bob_vertices& vertices);
                
        public:
                int materialIndex;
                bob_x3vertex_data x3vertexData;

                bob_face_list() { materialIndex=0; }
                
                bool load(ibinaryfilestream& is, bool x3data);
                bool toFile(obinaryfilestream& os, const bob_vertices& vertices, bool x3data);

                bool outputX3VertexDataRaw(otextfilestream& os);
                
                //bool computeAndOutputTangents(otextfilestream& os, const bob_point_map& pointMap);
};

class bob_part_collision_box
{
        public:
                point3d<double> sphereOffset;
                double sphereDiameter;
                point3d<double> boxOffset;
                point3d<double> boxSize;

        public:
                bob_part_collision_box() 
                { 
                        sphereDiameter = 0;
                }

                bool load(ibinaryfilestream& is);
                bool toFile(otextfilestream& os);
                bool toFile(obinaryfilestream& os);
};

class bob_part : public bob_with_errors, public ptr_list<ext::list<bob_face_list*> >
{
        public:
                static const int FLAG_X3 = 0x10000000;

                static const int BOD_FLAG_UV = 8;
                static const int BOD_FLAG_SGBITS = 16;

                int flags;
                bob_part_collision_box collisionBox;

        private:
                bool outputX3VertexData(otextfilestream& os, const bob_point_map& pointMap);
                void outputExtraPtInfo(otextfilestream& os, const bob_vertex *points[]);
                void outputNormals(otextfilestream& os, const bob_vertex *points[]);
                bool outputRaw(otextfilestream& os, const bob_point_map& pointMap, int idx);
                bool outputBOD(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map& pointMap, int idx);

        public:
                bob_part()      { flags=0; }

                size_t numFaces() const
                {
                        size_t count=0;
                        for(const_iterator &it=begin(); it!=end(); ++it){
                                count+=it->size();
                        }
                        return count;
                }

                // 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(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os, const bob_vertices& vertices);
                bool toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map& pointMap, int idx);

};

class bob_parts : public bob_section, public ext::list<bob_part*>
{
        public:
                static const int HDR_BEGIN = BOB_SECTION_NAME_PART_BEGIN;
                static const int HDR_END = BOB_SECTION_NAME_PART_END;

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os, const bob_vertices& vertices);
                bool toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map *pointMap);

                ~bob_parts()
                {
                        for(iterator &it=begin(); it!=end(); ++it){
                                delete *it;
                        }
                }
};

class bob_body : public bob_with_errors
{
        public:
                bob_bones bones;
                bob_vertices vertices;
                bob_parts parts;
                bob_weights weights;

                int bodySize;
                int bodyFlags;

                bob_body() { bodySize=0; bodyFlags=0; }

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, int idx);
};

class bob_bodies : public bob_section, public bob_cantainer<bob_body>
{
        public:
                static const int HDR_BEGIN = BOB_SECTION_NAME_BODY_BEGIN;
                static const int HDR_END = BOB_SECTION_NAME_BODY_END;

                bool load(ibinaryfilestream& is);

                bool toFile(obinaryfilestream& os);
                bool toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials);
};

class bob_dom_bob : public bob_section
{
        private:
                const Settings *m_settings;

        public:
                typedef bob_bodies::iterator BodyIterator;

                bob_info info;
                bob_materials materials;
                bob_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(obinaryfilestream& os);
                bool toFile(otextfilestream& os);

                bool load(ibinaryfilestream& is);

};

#endif // !defined(BOB_BOB_INCLUDED)