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)