void InterpretSortNorm(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; BSP_SortNorm snorm; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); snorm.Read((char *) curpos + blkhdr.MySize(), blkhdr); if (snorm.front_offset) BSPTransPMF(offset + snorm.front_offset, data, points, polygons, upolys); // continue traversal if (snorm.back_offset) BSPTransPMF(offset + snorm.back_offset, data, points, polygons, upolys); // continue traversal if (snorm.prelist_offset) BSPTransPMF(offset + snorm.prelist_offset, data, points, polygons, upolys); // continue traversal if (snorm.postlist_offset) BSPTransPMF(offset + snorm.postlist_offset, data, points, polygons, upolys); // continue traversal if (snorm.online_offset) BSPTransPMF(offset + snorm.online_offset, data, points, polygons, upolys); // continue traversal // No tail recursion on sortnorms }
void BSPTransPMF(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; //BSP_BoundBox *bbox; blkhdr.Read((char *) curpos); switch (blkhdr.id) { case 0: // End of Tree break; case 1: // DEFPOINTS points.Read((char *) curpos + blkhdr.MySize(), blkhdr); // interpret block BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal break; case 2: // Untextured Poly TranslateFPoly(offset, data, points, polygons, upolys); // interpret and continue break; case 3: // Textured Poly TranslateTPoly(offset, data, points, polygons, upolys); // interpret and continue break; case 4: // Sortnorm InterpretSortNorm(offset, data, points, polygons, upolys); // interpret and continue break; case 5: //boundbox BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal break; default: break; } }
void TranslateTPoly(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); vector3d point, norm; BSP_TmapPoly tpoly; pcs_polygon temp_poly; tpoly.Read((char *) curpos + blkhdr.MySize(), blkhdr); // 2^32-1 = 4294967295 // 2^8-1 = 255 temp_poly.norm = POFTranslate(tpoly.normal); temp_poly.texture_id = tpoly.tmap_num; temp_poly.verts.resize(tpoly.nverts); //norm = tpoly.normal for (int i = 0; i < tpoly.nverts; i++) { temp_poly.verts[i].point = POFTranslate(points.vertex_data[tpoly.verts[i].vertnum].vertex); temp_poly.verts[i].norm = POFTranslate(points.normals[tpoly.verts[i].normnum]); temp_poly.verts[i].u = tpoly.verts[i].u; temp_poly.verts[i].v = tpoly.verts[i].v; } if (upolys >= polygons.size()) { polygons.resize(polygons.size() * 2); } polygons[upolys] = temp_poly; upolys++; BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal }
void TranslateFPoly(unsigned int offset, unsigned char *data, BSP_DefPoints &points, std::vector<pcs_polygon> &polygons, unsigned int &upolys) { BSP_BlockHeader blkhdr; unsigned char *curpos = data + offset; blkhdr.Read((char *) curpos); vector3d point, norm; pcs_polygon temp_poly; BSP_FlatPoly fpoly; fpoly.Read((char *) curpos + blkhdr.MySize(), blkhdr); temp_poly.norm = POFTranslate(fpoly.normal); temp_poly.texture_id = -1; temp_poly.verts.resize(fpoly.nverts); for (int i = 0; i < fpoly.nverts; i++) { temp_poly.verts[i].point = POFTranslate(points.vertex_data[fpoly.verts[i].vertnum].vertex); temp_poly.verts[i].norm = POFTranslate(points.normals[fpoly.verts[i].normnum]); temp_poly.verts[i].u = 0; temp_poly.verts[i].v = 0; } if (upolys >= polygons.size()) { polygons.resize(polygons.size() * 2); } polygons[upolys] = temp_poly; upolys++; BSPTransPMF(offset + blkhdr.size, data, points, polygons, upolys); // continue traversal }
int PCS_Model::LoadFromPOF(std::string filename, AsyncProgress* progress) { this->Reset(); char cstringtemp[256]; progress->setMessage("Opening and Reading POF"); progress->Notify(); std::ifstream infile(filename.c_str(), std::ios::in | std::ios::binary); if (!infile) return 1; POF poffile(infile); progress->setTarget(4 + poffile.SPCL_Count() + poffile.GPNT_SlotCount() + poffile.MPNT_SlotCount() + poffile.TGUN_Count_Banks() + poffile.TMIS_Count_Banks() + poffile.DOCK_Count_Docks() + poffile.FUEL_Count_Thrusters() + poffile.INSG_Count_Insignia() + poffile.PATH_Count_Paths() + poffile.GLOW_Count_LightGroups() + poffile.OBJ2_Count()); // Update Progress progress->incrementWithMessage("Getting Header"); header.max_radius = poffile.HDR2_Get_MaxRadius(); header.max_radius_override = header.max_radius; header.min_bounding = poffile.HDR2_Get_MinBound(); header.max_bounding = poffile.HDR2_Get_MaxBound(); POFTranslateBoundingBoxes(header.min_bounding, header.max_bounding); header.min_bounding_override = header.min_bounding; header.max_bounding_override = header.max_bounding; unsigned int i, j, k; int scratch; // useless variable - for legacy remnant argument poffile.HDR2_Get_Details(scratch, header.detail_levels); poffile.HDR2_Get_Debris(scratch, header.debris_pieces); header.mass = poffile.HDR2_Get_Mass(); header.mass_center = POFTranslate(poffile.HDR2_Get_MassCenter()); poffile.HDR2_Get_MomentInertia(header.MOI); // --------- convert cross sections --------- std::vector<cross_section> sections; poffile.HDR2_Get_CrossSections(scratch, sections); if (scratch != -1) { header.cross_sections.resize(scratch); for (i = 0; i < header.cross_sections.size(); i++) { header.cross_sections[i].depth = sections[i].depth; header.cross_sections[i].radius = sections[i].radius; } } // --------- ACEN --------- // Update Progress progress->incrementWithMessage("Getting ACEN, TXTR, PINF, EYE"); autocentering = POFTranslate(poffile.ACEN_Get_acen()); // --------- TXTR --------- textures.resize(poffile.TXTR_Count_Textures()); std::string tmp_test; for (i = 0; i < textures.size(); i++) { tmp_test = poffile.TXTR_GetTextures(i); textures[i] = tmp_test; } // --------- ---------------------- --------- model_info = poffile.PINF_Get(); can_bsp_cache = false; for (i = 0; i < model_info.size(); i++) { if ( //strstr(model_info[i].c_str(), "BSPGEN") || // Volition's Compiler - caching revoked 2008-02-11 by Kazan because cannot gaurantee that tagged models actually game from V's compiler //strstr(model_info[i].c_str(), "POF-CS Compiler v1.3.4") || // removed PCS1 from recognized cacheable list 2008-01-10 - Kazan strstr(model_info[i].c_str(), PCS2_COMP_VERSION.mb_str())) { can_bsp_cache = true; break; } } // --------- EYE --------- eyes.resize(poffile.EYE_Count_Eyes()); for (i = 0; i < eyes.size(); i++) { poffile.EYE_Get_Eye(i, eyes[i].sobj_number, eyes[i].sobj_offset, eyes[i].normal); eyes[i].sobj_offset = POFTranslate(eyes[i].sobj_offset); eyes[i].normal = POFTranslate(eyes[i].normal); } // --------- SPCL --------- special.resize(poffile.SPCL_Count()); for (i = 0; i < special.size(); i++) { // Update Progress sprintf(cstringtemp, "Getting Special %d", i); progress->incrementWithMessage(cstringtemp); poffile.SPCL_Get_Special(i, special[i].name, special[i].properties, special[i].point, special[i].radius); special[i].point = POFTranslate(special[i].point); } // --------- weapons (GPNT/MPNT) --------- weapons.resize(poffile.GPNT_SlotCount() + poffile.MPNT_SlotCount()); for (i = 0; i < poffile.GPNT_SlotCount(); i++) { // Update Progress sprintf(cstringtemp, "Getting Gun Point %d", i); progress->incrementWithMessage(cstringtemp); weapons[i].type = GUN; weapons[i].muzzles.resize(poffile.GPNT_PointCount(i)); for (j = 0; j < poffile.GPNT_PointCount(i); j++) { poffile.GPNT_GetPoint(i, j, weapons[i].muzzles[j].point, weapons[i].muzzles[j].norm); weapons[i].muzzles[j].point = POFTranslate(weapons[i].muzzles[j].point); weapons[i].muzzles[j].norm = POFTranslate(weapons[i].muzzles[j].norm); } } k = poffile.GPNT_SlotCount(); for (i = 0; i < poffile.MPNT_SlotCount(); i++) { // Update Progress sprintf(cstringtemp, "Getting Missile Point %d", i); progress->incrementWithMessage(cstringtemp); weapons[i+k].type = MISSILE; weapons[i+k].muzzles.resize(poffile.MPNT_PointCount(i)); for (j = 0; j < poffile.MPNT_PointCount(i); j++) { poffile.MPNT_GetPoint(i, j, weapons[i+k].muzzles[j].point, weapons[i+k].muzzles[j].norm); weapons[i+k].muzzles[j].point = POFTranslate(weapons[i+k].muzzles[j].point); weapons[i+k].muzzles[j].norm = POFTranslate(weapons[i+k].muzzles[j].norm); } } // --------- turrets TGUN/TMIS --------- turrets.resize(poffile.TGUN_Count_Banks() + poffile.TMIS_Count_Banks()); for (i = 0; i < poffile.TGUN_Count_Banks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Gun Turret %d", i); progress->incrementWithMessage(cstringtemp); turrets[i].type = GUN; poffile.TGUN_Get_Bank(i, turrets[i].sobj_parent, turrets[i].sobj_par_phys, turrets[i].turret_normal); turrets[i].turret_normal = POFTranslate(turrets[i].turret_normal); turrets[i].fire_points.resize(poffile.TGUN_Count_Points(i)); for (j = 0; j < poffile.TGUN_Count_Points(i); j++) { poffile.TGUN_Get_FirePoint(i, j, turrets[i].fire_points[j]); turrets[i].fire_points[j] = POFTranslate(turrets[i].fire_points[j]); } } k = poffile.TGUN_Count_Banks(); for (i = 0; i < poffile.TMIS_Count_Banks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Missile Turret %d", i); progress->incrementWithMessage(cstringtemp); turrets[i+k].type = GUN; poffile.TMIS_Get_Bank(i, turrets[i+k].sobj_parent, turrets[i+k].sobj_par_phys, turrets[i+k].turret_normal); turrets[i+k].turret_normal = POFTranslate(turrets[i+k].turret_normal); turrets[i+k].fire_points.resize(poffile.TMIS_Count_Points(i)); for (j = 0; j < poffile.TMIS_Count_Points(i); j++) { poffile.TMIS_Get_FirePoint(i, j, turrets[i+k].fire_points[j]); turrets[i+k].fire_points[j] = POFTranslate(turrets[i+k].fire_points[j]); } } // --------- docking --------- docking.resize(poffile.DOCK_Count_Docks()); for (i = 0; i < poffile.DOCK_Count_Docks(); i++) { // Update Progress sprintf(cstringtemp, "Getting Docking Point %d", i); progress->incrementWithMessage(cstringtemp); poffile.DOCK_Get_DockProps(i, docking[i].properties); docking[i].dockpoints.resize(poffile.DOCK_Count_Points(i)); for (j = 0; j < poffile.DOCK_Count_Points(i); j++) { poffile.DOCK_Get_Point(i, j, docking[i].dockpoints[j].point, docking[i].dockpoints[j].norm); docking[i].dockpoints[j].point = POFTranslate(docking[i].dockpoints[j].point); docking[i].dockpoints[j].norm = POFTranslate(docking[i].dockpoints[j].norm); } docking[i].paths.resize(poffile.DOCK_Count_SplinePaths(i)); for (j = 0; j < poffile.DOCK_Count_SplinePaths(i); j++) { poffile.DOCK_Get_SplinePath(i, j, docking[i].paths[j]); } } // --------- thrusters --------- thrusters.resize(poffile.FUEL_Count_Thrusters()); for (i = 0; i < poffile.FUEL_Count_Thrusters(); i++) { // Update Progress sprintf(cstringtemp, "Getting Thruster %d", i); progress->incrementWithMessage(cstringtemp); poffile.FUEL_Get_ThrusterProps(i, thrusters[i].properties); thrusters[i].points.resize(poffile.FUEL_Count_Glows(i)); for (j = 0; j < poffile.FUEL_Count_Glows(i); j++) { poffile.FUEL_Get_GlowPoint(i, j, thrusters[i].points[j].radius, thrusters[i].points[j].pos, thrusters[i].points[j].norm); thrusters[i].points[j].pos = POFTranslate(thrusters[i].points[j].pos); thrusters[i].points[j].norm = POFTranslate(thrusters[i].points[j].norm); } } // --------- shield_mesh --------- // Update Progress progress->incrementWithMessage("Getting Shields"); shield_mesh.resize(poffile.SHLD_Count_Faces()); int fcs[3], nbs[3]; for (i = 0; i < shield_mesh.size(); i++) { poffile.SHLD_Get_Face(i, shield_mesh[i].face_normal, fcs, nbs); shield_mesh[i].face_normal = POFTranslate(shield_mesh[i].face_normal);\ for (j = 0; j < 3; j++) { poffile.SHLD_Get_Vertex(fcs[j], shield_mesh[i].corners[j]); shield_mesh[i].corners[j] = POFTranslate(shield_mesh[i].corners[j]); } } // --------- insignia --------- insignia.resize(poffile.INSG_Count_Insignia()); vector3d uv, vv; float *u = (float *)&uv, *v = (float *)&vv; for (i = 0; i < poffile.INSG_Count_Insignia(); i++) { // Update Progress sprintf(cstringtemp, "Getting Insignia %d", i); progress->incrementWithMessage(cstringtemp); poffile.INSG_Get_Insignia(i, insignia[i].lod, insignia[i].offset); insignia[i].offset = POFTranslate(insignia[i].offset); insignia[i].faces.resize(poffile.INSG_Count_Faces(i)); for (j = 0; j < poffile.INSG_Count_Faces(i); j++) { poffile.INSG_Get_Insig_Face(i, j, fcs, uv, vv); for (k = 0; k < 3; k++) { poffile.INSG_Get_Insig_Vertex(i, fcs[k], insignia[i].faces[j].verts[k]); insignia[i].faces[j].verts[k] = POFTranslate(insignia[i].faces[j].verts[k]); insignia[i].faces[j].u[k] = u[k]; insignia[i].faces[j].v[k] = v[k]; } } } // --------- ai_paths --------- ai_paths.resize(poffile.PATH_Count_Paths()); for (i = 0; i < poffile.PATH_Count_Paths(); i++) { // Update Progress sprintf(cstringtemp, "Getting Path %d", i); progress->incrementWithMessage(cstringtemp); poffile.PATH_Get_Path(i, ai_paths[i].name, ai_paths[i].parent); ai_paths[i].verts.resize(poffile.PATH_Count_Verts(i)); for (j = 0; j < poffile.PATH_Count_Verts(i); j++) { poffile.PATH_Get_Vert(i, j, ai_paths[i].verts[j].pos, ai_paths[i].verts[j].radius); ai_paths[i].verts[j].pos = POFTranslate(ai_paths[i].verts[j].pos); } } // --------- light arrays --------- light_arrays.resize(poffile.GLOW_Count_LightGroups()); pcs_glow_array *gla; for (i = 0; i < poffile.GLOW_Count_LightGroups(); i++) { // Update Progress sprintf(cstringtemp, "Getting Glow Array %d", i); progress->incrementWithMessage(cstringtemp); gla = &light_arrays[i]; poffile.GLOW_Get_Group(i, gla->disp_time, gla->on_time, gla->off_time, gla->obj_parent, gla->LOD, gla->type, gla->properties); gla->lights.resize(poffile.GLOW_Count_Glows(i)); for (j = 0; j < poffile.GLOW_Count_Glows(i); j++) { poffile.GLOW_Get_GlowPoint(i, j, gla->lights[j].radius, gla->lights[j].pos, gla->lights[j].norm); gla->lights[j].pos = POFTranslate(gla->lights[j].pos); gla->lights[j].norm = POFTranslate(gla->lights[j].norm); } } // --------- Sub object Consversion --------- subobjects.resize(poffile.OBJ2_Count()); if (can_bsp_cache) bsp_cache.resize(poffile.OBJ2_Count()); for (i = 0; i < poffile.OBJ2_Count(); i++) { // Update Progress sprintf(cstringtemp, "Getting Object %d", i); progress->incrementWithMessage(cstringtemp); pcs_sobj* obj = &subobjects[i]; poffile.OBJ2_Get_Parent(i, obj->parent_sobj); poffile.OBJ2_Get_Radius(i, obj->radius); obj->radius_override = obj->radius; poffile.OBJ2_Get_Offset(i, obj->offset); obj->offset = POFTranslate(obj->offset); poffile.OBJ2_Get_GeoCenter(i, obj->geometric_center); obj->geometric_center = POFTranslate(obj->geometric_center); poffile.OBJ2_Get_BoundingMin(i, obj->bounding_box_min_point); poffile.OBJ2_Get_BoundingMax(i, obj->bounding_box_max_point); POFTranslateBoundingBoxes(obj->bounding_box_min_point, obj->bounding_box_max_point); obj->bounding_box_min_point_override = obj->bounding_box_min_point; obj->bounding_box_max_point_override = obj->bounding_box_max_point; poffile.OBJ2_Get_Name(i, obj->name); poffile.OBJ2_Get_Props(i, obj->properties); int type; poffile.OBJ2_Get_MoveType(i, type); // -1 = none, 1 = rotate switch (type) { case 1: obj->movement_type = ROTATE; break; default: obj->movement_type = MNONE; } poffile.OBJ2_Get_MoveAxis(i, type); // -1 = none, 1 = X, 2 = Z, 3 = Y switch (type) { case 0: obj->movement_axis = MV_X; break; case 1: obj->movement_axis = MV_Z; break; case 2: obj->movement_axis = MV_Y; break; default: obj->movement_axis = ANONE; } // fast method int bspsz; char *bspdata = NULL; poffile.OBJ2_Get_BSPDataPtr(i, bspsz, bspdata); //OBJ2_Get_BSPData obj->polygons.resize(100); // good starting size; unsigned int used_polygons = 0; BSP_DefPoints points; BSPTransPMF(0, (unsigned char *)bspdata, points, obj->polygons, used_polygons); obj->polygons.resize(used_polygons); // resize to exact size if (can_bsp_cache) poffile.OBJ2_Get_BSPData(i, bsp_cache[i].bsp_data); //if (bspdata) // delete[] bspdata; //bspdata = NULL; } Transform(matrix(), vector3d()); header.max_radius_overridden = std::fabs(header.max_radius - header.max_radius_override) > 0.0001f; header.max_bounding_overridden = header.max_bounding != header.max_bounding_override; header.min_bounding_overridden = header.min_bounding != header.min_bounding_override; for (auto& sobj : subobjects) { sobj.radius_overridden = std::fabs(sobj.radius - sobj.radius_override) > 0.0001f; sobj.bounding_box_min_point_overridden = sobj.bounding_box_min_point != sobj.bounding_box_min_point_override; sobj.bounding_box_max_point_overridden = sobj.bounding_box_max_point != sobj.bounding_box_max_point_override; } return 0; }