Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "bob_dom_bob.h"#include "bob_stream_operators.h"//---------------------------------------------------------------------------------// BOB filebool bob_dom_bob::load(ibinaryfilestream& is){int hdr;is >> hdr;if(hdr!=HDR_BEGIN){error(e_badHeader);return false;}if(peek(is)==bob_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;}}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(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(otextfilestream& os){info.toFile(os);os << endl;materials.toFile(os);if(materials.size())os << endl;if(bodies.toFile(os, *m_settings, &materials)==false){for(bob_bodies::ErrorIterator &e_it=bodies.errors.begin(); e_it!=bodies.errors.end(); ++e_it){error(e_it->severity, e_it->code, "Bodies->%s", e_it->text);}return false;}return os.good();}//---------------------------------------------------------------------------------// MATERIAL - objectbool bob_material1::load(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_material1::toFile(obinaryfilestream& os){os << index << textureID << ambient << diffuse << specular;return os.good();}//---------------------------------------------------------------------------------bool bob_material1::toFile(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 - objectbool bob_material3::load(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_material3::toFile(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_material3::toFile(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();}//---------------------------------------------------------------------------------// MATERIAL5bool bob_material5::load(ibinaryfilestream& is){base::load(is);if(type > mat3)is >> lightMap;errorCode=is.fail() ? e_notEnoughData : e_noError;return !is.fail();}//---------------------------------------------------------------------------------bool bob_material5::toFile(obinaryfilestream& os){base::toFile(os);os << lightMap;return os.good();}//---------------------------------------------------------------------------------bool bob_material5::toFile(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(ibinaryfilestream &is){is >> name;if(is.fail()) return e_error;short t;is >> t;type=(Type)t;switch(type){case typeBool: // no breakcase 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(obinaryfilestream& os){os << name << (short) type;switch(type){case typeBool: // no breakcase 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(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_VALUESbob_error_codes bob_material6_values::load(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_material6_values::toFile(obinaryfilestream& os){os << (short)size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os);}return os.good();}//---------------------------------------------------------------------------------bool bob_material6_values::toFile(otextfilestream& os){os << (int)size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os);}return os.good();}//---------------------------------------------------------------------------------// MATERIAL6 - bigbob_error_codes bob_material6::Big::load(ibinaryfilestream& is){bob_error_codes errorCode;is >> technique >> effect;errorCode=values.load(is);return errorCode;}//---------------------------------------------------------------------------------bool bob_material6::Big::toFile(obinaryfilestream& os){os << technique << effect;values.toFile(os);return os.good();}//---------------------------------------------------------------------------------bool bob_material6::Big::toFile(otextfilestream& os){int old=os.flags();os << autoSemicolons << technique << effect;values.toFile(os);os.flags(old);return os.good();}//---------------------------------------------------------------------------------// MATERIAL 6 - smallbob_error_codes bob_material6::Small::load(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_material6::Small::toFile(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_material6::Small::toFile(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 6bool bob_material6::load(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_material6::toFile(obinaryfilestream& os){bool bRes;os << index << flags;if(big)bRes=big->toFile(os);elsebRes=small->toFile(os);return bRes;}//---------------------------------------------------------------------------------bool bob_material6::toFile(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 - sectionbool bob_materials::load(ibinaryfilestream& is){int hdr;bob_material::materialType type;is >> hdr;switch(hdr){case HDR_MAT5_BEGIN:type=bob_material::mat5;break;case HDR_MAT6_BEGIN:type=bob_material::mat6;break;default:error(e_badHeader);return false;}int matCount;is >> matCount;bob_material *m;for(int i=0; i < matCount; i++){switch(type) {case bob_material::mat5:m=new bob_material5();break;case bob_material::mat6:m=new bob_material6();break;}if(m->load(is)==false){error(m->errorCode, "material[%d]: %s", i, bob_traslate_error(m->errorCode));delete m;return false;}elsepush_back(m);}is >> hdr;if(hdr!=HDR_END)error(e_badEndHeader);return (hdr==HDR_END && !is.fail());}//---------------------------------------------------------------------------------bool bob_materials::toFile(obinaryfilestream& os){int hdr;if(size() && front()->type==bob_material::mat6)hdr=HDR_MAT6_BEGIN;elsehdr=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_materials::toFile(otextfilestream& os){for(iterator &it=begin(); it!=end(); ++it){it->toFile(os);os << endl;}return os.good();}//---------------------------------------------------------------------------------// BODIES - sectionbool bob_bodies::load(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_bodies::toFile(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_bodies::toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials){int i=1;os << noSemicolons << "// beginning of bodies (" << (int)size() << ')' << endl;for(iterator &it=begin(); it!=end(); ++it, ++i){if(it->toFile(os, settings, materials, i)==false){for(bob_body::ErrorIterator &e_it=it->errors.begin(); e_it!=it->errors.end(); ++e_it){error(e_it->severity, e_it->code, "Body[%d]->%s", i, e_it->text);}return false;}os << endl;}os << "// end of bodies" << endl;return os.good();}//---------------------------------------------------------------------------------// POINTS - sectionbool bob_vertices::load(ibinaryfilestream& is){int hdr;is >> hdr;if(hdr!=HDR_BEGIN){error(e_badHeader);return false;}int pointCount;is >> pointCount;map.create(pointCount);bob_vertex *ch;for(int i=0; i < pointCount; i++){ch=new bob_vertex();if(ch->load(is)==false){error(ch->errorCode, "point[%d]: %s", i, bob_traslate_error(ch->errorCode));delete ch;return false;}map.addPoint(ch);}is >> hdr;if(hdr!=HDR_END)error(e_badEndHeader);return hdr==HDR_END && !is.fail();}//---------------------------------------------------------------------------------bool bob_vertices::toFile(obinaryfilestream& os){os << HDR_BEGIN;if(new_vertices.size()){os << (int)new_vertices.size();for(VertexIterator &it=new_vertices.begin(); it!=new_vertices.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_vertices::toFile(otextfilestream& os, const Settings& settings){if(settings.rawMode())return outputRaw(os);elsereturn outputBOD(os);}//---------------------------------------------------------------------------------bool bob_vertices::outputBOD(otextfilestream& os){int oldf=os.flags();int i=0;os << noSemicolons << "// beginning of points (" << (int)map.uniquePointsSize() << ')' << endl << autoSemicolons;bob_vertex *p;while(p=map.nextUniquePoint()){p->toFile(os, i++);}os << noSemicolons << "-1; -1; -1; // points end" << endl << endl;os.flags(oldf);return os.good();}//---------------------------------------------------------------------------------bool bob_vertices::outputRaw(otextfilestream& os){int oldf=os.flags();int i=0;os << noSemicolons << "// Vertices begin (" << (int)map.pointsSize() << " - " << (int)map.uniquePointsSize() << " unique)" << endl << autoSemicolons;for(bob_point_map::iterator &it=map.begin(); it!=map.end(); ++it, i++){os << autoSemicolons<< it->x << it->y << it->z;if(it->hasTextureCoords()){os << noSemicolons << "\t\tUV: " << autoSemicolons<< it->textureCoords.x << it->textureCoords.y;}if(it->flags & bob_vertex::FLAG_WEIRD_STUFF){os << noSemicolons << "\tWeird coords: " << autoSemicolons<< it->weirdCoords.x << it->weirdCoords.y;}os << noSemicolons << "\tNormal: " << autoSemicolons<< it->normalVector.x << it->normalVector.y << it->normalVector.z<< noSemicolons << "\tSGBits: " << it->sgbits;os << noSemicolons << " // " << i << endl;}os << noSemicolons << "-1; -1; -1; // Vertices end" << endl << endl;os.flags(oldf);return os.good();}//---------------------------------------------------------------------------------// POINT - objectbool bob_vertex::load(ibinaryfilestream& is){/*possible types0x1F - normal + UV + 2 unk values0x1B - normal + UV0x19 - normal*/is >> flags >> *(vertex*)this;if((flags & FLAG_DEFAULT)!=FLAG_DEFAULT){errorCode=e_unkPointFlags;return false;}if(hasTextureCoords())is >> textureCoords;if(flags & FLAG_WEIRD_STUFF)is >> weirdCoords;is >> normalVector >> sgbits;if(is.fail())errorCode=e_notEnoughData;return !is.fail();}//---------------------------------------------------------------------------------bool bob_vertex::toFile(obinaryfilestream& os){// set the default bits before outputtingflags|=FLAG_DEFAULT;os << flags << *(dynamic_cast<vertex*>(this));if(hasTextureCoords())os << textureCoords;if(flags & FLAG_WEIRD_STUFF)os << weirdCoords;os << normalVector << sgbits;return os.good();}//---------------------------------------------------------------------------------bool bob_vertex::toFile(otextfilestream& os, int idx){// autoSemicolons is set by parent (points)int coords[3];getBodCoords(coords);os << coords[0] << coords[1] << coords[2];os << noSemicolons << "// " << idx << endl << autoSemicolons;return os.good();}//---------------------------------------------------------------------------------// X3 vertex_data_recordbool bob_x3vertex_data_record::load(ibinaryfilestream& is){is >> pointIndex >> tangent >> unk;return !is.fail();}//---------------------------------------------------------------------------------bool bob_x3vertex_data_record::toFile(obinaryfilestream& os){os << pointIndex << tangent << unk;return os.good();}//---------------------------------------------------------------------------------/*int compare_x3vertex_rec(const void *a, const void *b){const bob_x3vertex_data_record *rec1=*((bob_x3vertex_data_record**)a), *rec2=*((bob_x3vertex_data_record**)b);return rec1->pointIndex - rec2->pointIndex;}*///---------------------------------------------------------------------------------// X3 uv listbool bob_x3vertex_data::load(ibinaryfilestream& is){int count;bob_x3vertex_data_record *rec;is >> count;reserve(count);for(int i=0; i < count; i++){rec=new bob_x3vertex_data_record();if(!rec->load(is)){delete rec;return false;}push_back(rec);}/*there should never be the need to compare the data, because they are written in the order of vertices,and thus their vertex indexes are always in sequence*///sort(compare_x3vertex_rec);return !is.fail();}//---------------------------------------------------------------------------------bool bob_x3vertex_data::toFile(obinaryfilestream& os){os << (int) size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os);}return os.good();}//---------------------------------------------------------------------------------// FACE LISTbool bob_face_list::load(ibinaryfilestream& is, bool x3data){int count;is >> materialIndex >> count;for(int i=0; i < count; i++){bob_face *face=new bob_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 && x3vertexData.load(is)==false) return false;return !is.fail();}//---------------------------------------------------------------------------------bool bob_face_list::toFile(obinaryfilestream& os, const bob_vertices& vertices, bool x3data){os << materialIndex << (int)size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os);}if(x3data)saveVertexTangents(os, vertices);return os.good();}//---------------------------------------------------------------------------------bool bob_face_list::saveVertexTangents(obinaryfilestream& os, const bob_vertices& vertices){// the still unknown God damned vectorvector vec1(0,0,1); // default valuevector vec0(0,0,0); // zero valuebool *vert_map=new bool[vertices.new_vertices.size()];memset(vert_map, 0, vertices.new_vertices.size() * sizeof(bool));size_t count_pos=os.tell();os << 123; // dummy countint idx, count=0;for(iterator &it=begin(); it!=end(); ++it){for(int i=0; i < 3; i++){idx=it->values[i];if(vert_map[idx]==false) {vector &tan=vertices.new_vertices[idx]->tangentVector;os << idx << tan << (tan.isZero() ? vec0 : vec1);vert_map[idx]=true;count++;}}}delete[] vert_map;// write the real countsize_t lastp=os.tell();os.seek((int)count_pos, mystream::stream_base::seek_begin);os << count;os.seek((int)lastp, mystream::stream_base::seek_begin);return os.good();}//---------------------------------------------------------------------------------bool bob_face_list::outputX3VertexDataRaw(otextfilestream& os){if(x3vertexData.size()==0) return true;int old=os.flags();os << noSemicolons << "// Material " << materialIndex << endl;os << "// Material; point index; tangent; unknown" << endl << autoSemicolons;for(bob_x3vertex_data::const_iterator &it=x3vertexData.begin(); it!=x3vertexData.end(); ++it){os << materialIndex << it->pointIndex << it->tangent << it->unk << endl;}os << endl;os.flags(old);return os.good();}//---------------------------------------------------------------------------------/*bool bob_face_list::computeAndOutputTangents(otextfilestream& os, const bob_point_map& pointMap){vertex v1, v2, v3;geometry::point2d<double> w1,w2,w3;int i1,i2,i3;vector *tan1, *tan2;tan1=new vector[pointMap.pointsSize() * 2];tan2=tan1 + pointMap.pointsSize();for(iterator &it=begin(); it!=end(); ++it){i1=it->values[0]; i2=it->values[1]; i3=it->values[2];v1=*pointMap[i1];v2=*pointMap[i2];v3=*pointMap[i3];w1=pointMap[i1]->textureCoords;w2=pointMap[i2]->textureCoords;w3=pointMap[i3]->textureCoords;double x1 = v2.x - v1.x;double x2 = v3.x - v1.x;double y1 = v2.y - v1.y;double y2 = v3.y - v1.y;double z1 = v2.z - v1.z;double z2 = v3.z - v1.z;double s1 = w2.x - w1.x;double s2 = w3.x - w1.x;double t1 = w2.y - w1.y;double t2 = w3.y - w1.y;double cp=s1 * t2 - s2 * t1;if(cp!=0) {double r = 1.0 / cp;vector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,(t2 * z1 - t1 * z2) * r);vector tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,(s1 * z2 - s2 * z1) * r);tan1[i1] += sdir;tan1[i2] += sdir;tan1[i3] += sdir;tan2[i1] += tdir;tan2[i2] += tdir;tan2[i3] += tdir;}}int oldf=os.flags();os << noSemicolons << "// vertex tangents" << autoSemicolons << endl;int i=0;for(bob_point_map::const_iterator &it=pointMap.begin(); it!=pointMap.end(); ++it, i++){const vector& n=it->normalVector;const vector& t=tan1[i];const vector& bt=tan2[i];// Gram-Schmidt orthogonalizevector tangent = (t - n * n.dot(t)).normalize();os << i << tangent << endl;}delete[] tan1;os.flags(oldf);return os.good();}*///---------------------------------------------------------------------------------// PARTS - section PARTbool bob_parts::load(ibinaryfilestream& is){int hdr, count;is >> hdr;if(hdr!=HDR_BEGIN){error(e_badHeader);return false;}is >> count;bob_part *part;for(int i=0; i < count; i++){part=new bob_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_parts::toFile(obinaryfilestream& os, const bob_vertices& vertices){os << HDR_BEGIN << (int) size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os, vertices);}os << HDR_END;return os.good();}//---------------------------------------------------------------------------------bool bob_parts::toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map *pointMap){int i=1;for(iterator &it=begin(); it!=end(); ++it, ++i){if(it->toFile(os, settings, materials, *pointMap, i)==false){for(bob_part::ErrorIterator &e_it=it->errors.begin(); e_it!=it->errors.end(); ++e_it){error(e_it->severity, e_it->code, "Part[%d]->%s", i, e_it->text);}return false;}}return os.good();}//---------------------------------------------------------------------------------bool bob_part_collision_box::load(ibinaryfilestream& is){is >> sphereOffset >> sphereDiameter;is >> boxOffset >> boxSize;return !is.fail();}//---------------------------------------------------------------------------------bool bob_part_collision_box::toFile(obinaryfilestream& os){os << sphereOffset << sphereDiameter;os << boxOffset << boxSize;return os.good();}//---------------------------------------------------------------------------------bool bob_part_collision_box::toFile(otextfilestream& os){int old=os.flags();os << noSemicolons;os << "/! COLLISION_BOX: " << autoSemicolons;os << boxOffset.x << boxOffset.y << boxOffset.z;os << sphereDiameter << boxSize.x << boxSize.y << boxSize.z;os << noSemicolons << "!/" << autoSemicolons << endl;os.flags(old);return os.good();}//---------------------------------------------------------------------------------// PARTS - objectbool bob_part::load(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 & FLAG_X3) > 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 & FLAG_X3)collisionBox.load(is);return !is.fail();}//---------------------------------------------------------------------------------bool bob_part::toFile(obinaryfilestream& os, const bob_vertices& vertices){os << flags << (short)size();for(iterator &it=begin(); it!=end(); ++it){it->toFile(os, vertices, (flags & FLAG_X3) > 0);}if(flags & FLAG_X3)collisionBox.toFile(os);return os.good();}//---------------------------------------------------------------------------------bool bob_part::toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map& pointMap, int idx){if(settings.rawMode())return outputRaw(os, pointMap, idx);elsereturn outputBOD(os, settings, materials, pointMap, idx);}//---------------------------------------------------------------------------------bool bob_part::outputBOD(otextfilestream& os, const Settings& settings, const bob_materials *materials, const bob_point_map& pointMap, int idx){bob_face *face;const bob_vertex *pnt;int line=0;int materialIndex;int oldf=os.flags();os << noSemicolons << "// ----- part " << idx << " (" << (int)numFaces() << " faces) -----" << endl << autoSemicolons;for(iterator &facelist_it=begin(); facelist_it!=end(); ++facelist_it){materialIndex=facelist_it->materialIndex;for(bob_face_list::iterator &face_it=facelist_it->begin(); face_it!=facelist_it->end(); ++face_it, ++line){face=*face_it;os << autoSemicolons << materialIndex;for(int i=0; i < 3; i++){os << pointMap.uniqueIndex(face->values[i]);}pnt=pointMap[face->values[0]];if(pnt==NULL){error(e_pointNotFound);return false;}int SGBits=pnt->sgbits;int magic = 1; // bit 1 is always set/*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 -17if there are materials and last value of the first point is non zero,magic is -25, otherwise it's -9*/const bob_vertex *points_ar[3];for(int i=0; i < 3; i++){pnt=pointMap[face->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]->hasTextureCoords())break;}if(bHasUV)magic|=BOD_FLAG_UV;if(SGBits)magic|=BOD_FLAG_SGBITS;os << (magic * -1);if(SGBits!=0)os << SGBits;// we have uv coords, lets output themif(bHasUV){for(int i=0; i < 3; i++){os << points_ar[i]->textureCoords; // correct output}os << noSemicolons << "/! ";outputNormals(os, points_ar);if(settings.extraPntInfo())outputExtraPtInfo(os, points_ar);os << noSemicolons << "!/ ";}os << noSemicolons << "// " << line << endl;}}// x3 dataif(flags & FLAG_X3){collisionBox.toFile(os);}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();}//---------------------------------------------------------------------------------bool bob_part::outputX3VertexData(otextfilestream& os, const bob_point_map& pointMap){int old=os.flags();os << endl << noSemicolons<< "// X3 vertex data (tangent and <unknown>)" << endl<< autoSemicolons;int i=1;for(iterator &facelist_it=begin(); facelist_it!=end(); ++facelist_it, i++){facelist_it->outputX3VertexDataRaw(os);//facelist_it->computeAndOutputTangents(os, pointMap);}os.flags(old);return true;}//---------------------------------------------------------------------------------void bob_part::outputNormals(otextfilestream& os, const bob_vertex *points[]){int oldf=os.flags();bool bSame=true;for(int i=1; i < 3; i++){bSame&=points[i]->normalVector == points[i - 1]->normalVector;}os << noSemicolons << "N: { " << autoSemicolons;for(int i=0; i < (bSame ? 1 : 3); i++){os << points[i]->normalVector;}os << noSemicolons << "} ";os.flags(oldf);}//---------------------------------------------------------------------------------// 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 x2void bob_part::outputExtraPtInfo(otextfilestream& os, const bob_vertex *points[]){int oldf=os.flags();bool bInfo=false;for(int i=0; i < 3; i++){bInfo|=(points[i]->flags & bob_vertex::FLAG_WEIRD_STUFF) > 0;}if(bInfo==false) return;os << noSemicolons << "XPINFO: ";for(int i=0; i < 3; i++){os << noSemicolons << "{ " << autoSemicolons<< points[i]->weirdCoords<< noSemicolons << "} ";}os.flags(oldf);}//---------------------------------------------------------------------------------// PART - objectbool bob_face::load(ibinaryfilestream& is){for(int i=0; i < 3; i++){is >> values[i];}is >> flags;if(is.fail())errorCode=e_notEnoughData;return !is.fail();}//---------------------------------------------------------------------------------bool bob_face::toFile(obinaryfilestream& os){for(int i=0; i < 3; i++){os << values[i];}os << flags;return os.good();}//---------------------------------------------------------------------------------bool bob_body::load(ibinaryfilestream& is){is >> bodySize >> bodyFlags;if(peek(is)==bob_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_vertices::HDR_BEGIN){if(vertices.load(is)==false){for(ErrorIterator &it=vertices.errors.begin(); it!=vertices.errors.end(); ++it){error(it->code, "vertices->%s", it->text);}return false;}}if(peek(is)==bob_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_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_body::toFile(obinaryfilestream& os){os << bodySize << bodyFlags;bones.toFile(os);vertices.toFile(os);weights.toFile(os);parts.toFile(os, vertices);return os.good();}//---------------------------------------------------------------------------------bool bob_body::toFile(otextfilestream& os, const Settings& settings, const bob_materials *materials, int idx){os << "// beginning of body " << idx << endl;os << autoSemicolons << bodySize << endl << endl;bones.toFile(os);vertices.toFile(os, settings);weights.toFile(os, &vertices.map);if(parts.toFile(os, settings, materials, &vertices.map)==false){for(bob_parts::ErrorIterator &e_it=parts.errors.begin(); e_it!=parts.errors.end(); ++e_it){error(e_it->severity, e_it->code, "Parts->%s", e_it->text);}return false;}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();}//---------------------------------------------------------------------------------// BONESbool bob_bones::load(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_bones::toFile(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_bones::toFile(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 - sectionbool bob_weights::load(ibinaryfilestream& is){int hdr;is >> hdr;if(hdr!=HDR_BEGIN){error(e_badHeader);return false;}int count;is >> count;resize(count);bob_weight *ch;for(int i=0; i < count; i++){ch=new bob_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_weights::toFile(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_weights::toFile(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 - objectbool bob_weight::load(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_weight::toFile(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_weight::toFile(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();}//---------------------------------------------------------------------------------bool bob_part::outputRaw(otextfilestream& os, const bob_point_map& pointMap, int idx){int oldf=os.flags();os << noSemicolons << "// Part " << idx << endl << "// " << (int)numFaces() << " faces" << endl;for(iterator& facelist_it=begin(); facelist_it!=end(); ++facelist_it){os << noSemicolons << "// Material " << facelist_it->materialIndex << endl << autoSemicolons;for(bob_face_list::iterator& face_it=facelist_it->begin(); face_it!=facelist_it->end(); ++face_it){for(int i=0; i < 3; i++)os << face_it->values[i];os << face_it->flags;os << endl;}}bool bRes = true;if(flags & FLAG_X3) {bRes = outputX3VertexData(os, pointMap);os << noSemicolons << "Collision sphere: offset: " << autoSemicolons << collisionBox.sphereOffset.x << collisionBox.sphereOffset.y << collisionBox.sphereOffset.z << noSemicolons << "diameter: " << autoSemicolons << collisionBox.sphereDiameter << endl;os << noSemicolons << "Collision box: offset: " << autoSemicolons << collisionBox.boxOffset.x << collisionBox.boxOffset.y << collisionBox.boxOffset.z << noSemicolons << "size: " << autoSemicolons << collisionBox.boxSize.x << collisionBox.boxSize.y << collisionBox.boxSize.z << endl;}os.flags(oldf);return os.good() && bRes;}//---------------------------------------------------------------------------------