/* * .3DS loader hacked up for barbecue * TODO: change loader to use MeshObject class natively, atm it's a dirty hack * References: * http://www.the-labs.com/Blender/3DS-details.html */ #include #include "loader3DS.h" #include "FileIO.h" #include "chunk_defines3DS.h" #include "Init.h" using namespace std; using namespace exh; #define DEBUG3DS CObject obj; CObjectMaterial::CObjectMaterial(void) { material_name = new string(""); texture_name = new string(""); } CObjectMaterial::~CObjectMaterial(void) { // delete material_name; // delete texture_name; } CObjectModel::CObjectModel(void) { // object_name = new string(""); object_name = NULL; mat = vector(); point = vector(); face = vector(); tex = vector(); } CObjectModel::~CObjectModel(void) { // delete object_name; } CObject::CObject(void) { vecmodel = vector(); vecmaterial = vector(); //default options master_scale = 1.0f; isMaterial = true; } MeshObject* CObject::loadModel(string filename) { exh::FileIO reader; if (!reader.open(exh::init.getDataPath(filename.c_str()))) { fprintf(stderr, "Failed to load file %s\n", filename.c_str()); return NULL; } //returns the position of the material in an array map materialMap = map(); CObjectMaterial *tmp_material = new CObjectMaterial; CObjectModel *tmp_model = new CObjectModel; Vector tmpVector; FACE_ARRAY_ABC tmpFace; TEX_VERT_UV tmpTex; COLOR *tmpColor = new COLOR; Uint16 *tmpPercentage = new Uint16; bool isFirstModel = true, isFirstMaterial = true; Uint32 chunk_len, tmpi; Uint16 chunk_sub_elements, chunk_face_flags, chunk_id, tmps; float tmpf; int i; char tmpc; string tmpstr; while(!reader.isEnd()) { chunk_id = reader.readUInt16(); chunk_len = reader.readUInt32(); switch (chunk_id) { //.3ds file magic numbers case M3DMAGIC: break; case MDATA: break; //color chunks case 0x0010: //COLOR_F tmpColor->r = reader.readFloat(); tmpColor->g = reader.readFloat(); tmpColor->b = reader.readFloat(); #ifdef DEBUG3DS printf("\tCOLOR_F: %.2f %.2f %.2f\n",tmpColor->r,tmpColor->g,tmpColor->b); #endif break; case 0x0011: //COLOR_24 /* way to go dipshit! you obviously forgot calculation rules: -(-x) = +x */ tmpc = reader.readChar(); tmpColor->r = (tmpc<0?255+tmpc:tmpc)/255.0f; tmpc = reader.readChar(); tmpColor->g = (tmpc<0?255+tmpc:tmpc)/255.0f; tmpc = reader.readChar(); tmpColor->b = (tmpc<0?255+tmpc:tmpc)/255.0f; #ifdef DEBUG3DS printf("\tCOLOR_24: %.2f %.2f %.2f\n",tmpColor->r,tmpColor->g,tmpColor->b); #endif break; case 0x0012: //LIN_COLOR_24 tmpc = reader.readChar(); tmpColor->r = (tmpc<0?255+tmpc:tmpc)/255.0f; tmpc = reader.readChar(); tmpColor->g = (tmpc<0?255+tmpc:tmpc)/255.0f; tmpc = reader.readChar(); tmpColor->b = (tmpc<0?255+tmpc:tmpc)/255.0f; #ifdef DEBUG3DS printf("\tLIN_COLOR_24: %.2f %.2f %.2f\n",tmpColor->r,tmpColor->g,tmpColor->b); #endif break; case 0x0013: //LIN_COLOR_F tmpColor->r = reader.readFloat(); tmpColor->g = reader.readFloat(); tmpColor->b = reader.readFloat(); #ifdef DEBUG3DS printf("\tLIN_COLOR_F: %.2f %.2f %.2f\n",tmpColor->r,tmpColor->g,tmpColor->b); #endif break; //percentage chunks case 0x0030: //INT_PERCENTAGE *tmpPercentage = reader.readUInt16(); //value might be for example 5120 which means 51.2 //let's fix these kind of values if (*tmpPercentage > 1000) { *tmpPercentage /= 100; } #ifdef DEBUG3DS printf("\tINT_PERCENTAGE: %i\n",*tmpPercentage); #endif //point variable to other variable just to avoid //reseting the old variable tmpPercentage = &tmps; break; case 0x0031: //FLOAT_PERCENTAGE tmpf = reader.readFloat(); *tmpPercentage = (short)(tmpf*100); #ifdef DEBUG3DS printf("\tFLOAT_PERCENTAGE: %.2f -> %i\n",tmpf,*tmpPercentage); #endif tmpPercentage = &tmps; break; case 0x0100: //MASTER_SCALE master_scale = reader.readFloat(); #ifdef DEBUG3DS printf("MASTER_SCALE: %.2f\n",master_scale); #endif break; //OBJECTS //new object's entry point //get the name of the object (cstr) case 0x4000: //NAMED_OBJECT if (!isFirstModel) { vecmodel.push_back(*tmp_model); //clear vectors tmp_model->mat.clear(); tmp_model->point.clear(); tmp_model->face.clear(); tmp_model->tex.clear(); } else { isFirstModel = false; } tmp_model->object_name = new string(reader.readCStr()); #ifdef DEBUG3DS printf("Model Name: %s\n",tmp_model->object_name->c_str()); #endif break; //mesh data entry case 0x4100: //N_TRI_OBJECT break; case 0x4110: //POINT_ARRAY chunk_sub_elements = reader.readUInt16(); #ifdef DEBUG3DS printf("4110 POINT_ARRAY chunk_sub_elements: %d\n", chunk_sub_elements); #endif for (i=0; ipoint.push_back(tmpVector); } break; case 0x4120: //FACE_ARRAY chunk_sub_elements = reader.readUInt16(); #ifdef DEBUG3DS printf("4120 FACE_ARRAY chunk_sub_elements: %d\n", chunk_sub_elements); #endif for (i=0; iface.push_back(tmpFace); } break; case 0x4130: //MSH_MAT_GROUP tmpstr = reader.readCStr(); tmpi = materialMap[tmpstr]; #ifdef DEBUG3DS printf("\tUse Material Name: %s\n",tmpstr.c_str()); #endif chunk_sub_elements = reader.readUInt16(); for (i=0; imat.size()) { tmp_model->mat[tmps] = tmpi; } else { for(int j=tmp_model->mat.size(); j<=tmps; j++) { tmp_model->mat.push_back(tmpi); } } } break; case 0x4140: //TEX_VERTS chunk_sub_elements = reader.readUInt16(); #ifdef DEBUG3DS printf("4140 TEX_VERTS chunk_sub_elements: %d\n", chunk_sub_elements); #endif for (i=0; itex.push_back(tmpTex); } break; //MATERIALS case 0xa000: //MAT_NAME tmp_material->transparencyf = ((100-tmp_material->transparency)/100.0); if (!isFirstMaterial) { vecmaterial.push_back(*tmp_material); } else { isFirstMaterial = false; } tmp_material->material_name = new string(reader.readCStr()); materialMap[*tmp_material->material_name] = vecmaterial.size(); #ifdef DEBUG3DS printf("Material Name: %s\n",tmp_material->material_name->c_str()); #endif break; //get color chunk(s) case 0xa010: //MAT_AMBIENT #ifdef DEBUG3DS printf("\tMAT_AMBIENT -> "); #endif tmpColor = &tmp_material->ambient; break; case 0xa020: //MAT_DIFFUSE #ifdef DEBUG3DS printf("\tMAT_DIFFUSE -> "); #endif tmpColor = &tmp_material->diffuse; break; case 0xa030: //MAT_SPECULAR #ifdef DEBUG3DS printf("\tMAT_SPECULAR -> "); #endif tmpColor = &tmp_material->specular; break; //get percent chunk case 0xa040: //MAT_SHININESS #ifdef DEBUG3DS printf("\tMAT_SHININESS -> "); #endif tmpPercentage = &tmp_material->shininess; break; case 0xa050: //MAT_TRANSPARENCY #ifdef DEBUG3DS printf("\tMAT_TRANSPARENCY -> "); #endif tmpPercentage = &tmp_material->transparency; break; //Read the chunk so that we can read MAT_MAPNAME case 0xa200: //MAT_TEXMAP break; //name of the texture case 0xa300: //MAT_MAPNAME tmp_material->texture_name = new string(reader.readCStr()); #ifdef DEBUG3DS printf("\tBitmap Name: %s\n",tmp_material->texture_name->c_str()); #endif break; case 0xafff: //MAT_ENTRY break; default: #ifdef DEBUG3DS printf("Not Handled ID: %x (%x)\n",chunk_id,chunk_len); #endif reader.readSkip(chunk_len-6); break; } } reader.close(); if(isFirstMaterial) { isMaterial = false; } tmp_material->transparencyf = ((100-tmp_material->transparency)/100.0); vecmaterial.push_back(*tmp_material); vecmodel.push_back(*tmp_model); return this->display(filename); } MeshObject* CObject::display(string filename) { CObjectModel *tmp_model; FACE_ARRAY_ABC *face; MeshObject *meshObject = new MeshObject(); meshObject->name = filename; meshObject->setObjectSize(vecmodel.size()); meshObject->setMaterialSize(vecmaterial.size()); for(size_t k=0; k < vecmaterial.size(); k++) { meshObject->material[k].material_name = *vecmaterial[k].material_name; meshObject->material[k].texture_name = *vecmaterial[k].texture_name; meshObject->material[k].ambient.r = vecmaterial[k].ambient.r; meshObject->material[k].ambient.g = vecmaterial[k].ambient.g; meshObject->material[k].ambient.b = vecmaterial[k].ambient.b; meshObject->material[k].diffuse.r = vecmaterial[k].diffuse.r; meshObject->material[k].diffuse.g = vecmaterial[k].diffuse.g; meshObject->material[k].diffuse.b = vecmaterial[k].diffuse.b; meshObject->material[k].specular.r = vecmaterial[k].specular.r; meshObject->material[k].specular.g = vecmaterial[k].specular.g; meshObject->material[k].specular.b = vecmaterial[k].specular.b; meshObject->material[k].transparency = vecmaterial[k].transparencyf; meshObject->material[k].shininess = (unsigned int)vecmaterial[k].shininess; } for(size_t i=0, sizeModels=vecmodel.size(); iobject_name) { meshObject->object[i].name = *(tmp_model->object_name); } meshObject->object[i].setFaceTriangleSize(tmp_model->face.size()); meshObject->object[i].setVertexSize(tmp_model->point.size()); for(j=0;jpoint.size();j++) { meshObject->object[i].vertex[j] = tmp_model->point[j]; } meshObject->object[i].setTexCoordSize(tmp_model->tex.size()); for(j=0;jtex.size();j++) { meshObject->object[i].tex_coord[j].u = tmp_model->tex[j].u; meshObject->object[i].tex_coord[j].v = tmp_model->tex[j].v; } for (j=0;jface.size();j++) { face = &tmp_model->face[j]; meshObject->object[i].faceTriangle[j].material = &meshObject->material[tmp_model->mat[j]]; meshObject->object[i].faceTriangle[j].v1.vertex = &meshObject->object[i].vertex[face->a]; meshObject->object[i].faceTriangle[j].v1.tex_coord = &meshObject->object[i].tex_coord[face->a]; meshObject->object[i].faceTriangle[j].v2.vertex = &meshObject->object[i].vertex[face->b]; meshObject->object[i].faceTriangle[j].v2.tex_coord = &meshObject->object[i].tex_coord[face->a]; meshObject->object[i].faceTriangle[j].v3.vertex = &meshObject->object[i].vertex[face->c]; meshObject->object[i].faceTriangle[j].v3.tex_coord = &meshObject->object[i].tex_coord[face->a]; } } return meshObject; }