void MakeDefPoints(BSP_DefPoints& dpnts, std::vector<bsp_vert> &pntslist) { dpnts.head.id = 1; dpnts.n_verts = pntslist.size(); dpnts.n_norms = 0; dpnts.offset = 20 + pntslist.size(); dpnts.norm_counts.resize(pntslist.size()); dpnts.vertex_data.resize(pntslist.size()); for (unsigned int i = 0; i < pntslist.size(); i++) { dpnts.norm_counts[i] = (unsigned char)pntslist[i].norms.size(); dpnts.vertex_data[i].vertex = pntslist[i].point; dpnts.vertex_data[i].norms.resize(pntslist[i].norms.size()); dpnts.n_norms += pntslist[i].norms.size(); for (unsigned int j = 0; j < pntslist[i].norms.size(); j++) { dpnts.vertex_data[i].norms[j] = pntslist[i].norms[j]; } } // last thing dpnts.head.size = dpnts.MySize(); }
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; } }
std::string BSP::DataIn(char *buffer, int size) { std::string stats; char *localptr = buffer; char cstemp[64]; bool go = true; BSP_BoundBox bnd; BSP_DefPoints pnt; BSP_FlatPoly fpol; BSP_SortNorm snrm; BSP_TmapPoly tpol; BSP_BlockHeader head; stats = ""; //0 - EOF, 1 - DEFPOINTS, 2 - FLATPOLY, 3 - IMAPPOLY, 4- SHORNORM, 5- BOUNDBOX while (go) { head.Read(localptr); localptr += 8; if (localptr - buffer >= size) { go = false; break; } switch (head.id) { case 0: //stats += "EOF\n"; //stats += "\n"; //go = false; break; case 1: memset(cstemp, 0, 64); sprintf(cstemp, "[%d bytes (%d bytes unused)]", head.size, head.size - pnt.Read(localptr, head)); localptr += (head.size - 8);//8 for the already added header //stats += "DEFPOINTS "; //stats += cstemp; //stats += "\n"; /* memset(cstemp, 0, 64); sprintf(cstemp, "%d", pnt.n_norms); stats += " +n_norms: "; stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, "%d", pnt.n_verts); stats += " +n_verts: "; stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, "%d", pnt.offset); stats += " +offset: +"; stats += cstemp; stats += "\n"; Collector = 0; for (i = 0; i < pnt.n_verts; i++) { if (i < pnt.n_norms) Collector += int(unsigned char(pnt.norm_counts[i])); } memset(cstemp, 0, 64); sprintf(cstemp, "%d bytes", sizeof(vector) * (Collector + pnt.n_verts)); stats += " +vertex data size: "; stats += cstemp; stats += "\n";*/ //stats += "\n"; Add_DefPoints(pnt); break; case 2: //stats += "FLATPOLY "; memset(cstemp, 0, 64); sprintf(cstemp, "[%d bytes (%d bytes unused)]", head.size, head.size - fpol.Read(localptr, head)); localptr += (head.size - 8);//8 for the already added header /*memset(cstemp, 0, 64); sprintf(cstemp, " @+ Red: %d, Green: %d, Blue: %d, Pad: %d", fpol.red, fpol.green, fpol.blue, fpol.pad); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ Normal: (%f, %f, %f), Radius %f", fpol.normal.x, fpol.normal.y, fpol.normal.z, fpol.radius); stats += cstemp; stats += "\n"; for (i = 0; i < fpol.nverts; i++) { memset(cstemp, 0, 64); sprintf(cstemp, " @+ Point: (%f, %f, %f),", points[0].vertex_data[fpol.verts[i].vertnum].vertex.x, points[0].vertex_data[fpol.verts[i].vertnum].vertex.y, points[0].vertex_data[fpol.verts[i].vertnum].vertex.z); stats += cstemp; memset(cstemp, 0, 64); sprintf(cstemp, " Normal: (%f, %f, %f),", points[0].vertex_data[fpol.verts[i].vertnum].norms[fpol.verts[i].normnum].x, points[0].vertex_data[fpol.verts[i].vertnum].norms[fpol.verts[i].normnum].y, points[0].vertex_data[fpol.verts[i].vertnum].norms[fpol.verts[i].normnum].z); stats += cstemp; stats += "\n"; }*/ //stats += "\n"; Add_FlatPoly(fpol); break; case 3: // stats += "IMAPPOLY "; memset(cstemp, 0, 64); sprintf(cstemp, "[%d bytes (%d bytes unused)]", head.size, head.size - tpol.Read(localptr, head)); localptr += (head.size - 8);//8 for the already added header //stats += cstemp; //stats += "\n"; /*memset(cstemp, 0, 64); sprintf(cstemp, " @+ Normal: (%f, %f, %f), Radius %f", tpol.normal.x, tpol.normal.y, tpol.normal.z, tpol.radius); stats += cstemp; stats += "\n"; for (i = 0; i < tpol.nverts; i++) { memset(cstemp, 0, 64); sprintf(cstemp, " @+ Point: (%f, %f, %f),", points[0].vertex_data[tpol.verts[i].vertnum].vertex.x, points[0].vertex_data[tpol.verts[i].vertnum].vertex.y, points[0].vertex_data[tpol.verts[i].vertnum].vertex.z); stats += cstemp; memset(cstemp, 0, 64); sprintf(cstemp, " Normal: (%f, %f, %f),", points[0].vertex_data[tpol.verts[i].vertnum].norms[tpol.verts[i].normnum].x, points[0].vertex_data[tpol.verts[i].vertnum].norms[tpol.verts[i].normnum].y, points[0].vertex_data[tpol.verts[i].vertnum].norms[tpol.verts[i].normnum].z); stats += cstemp; stats += "\n"; }*/ //stats += "\n"; Add_TmapPoly(tpol); break; case 4: stats += "SORTNORM "; memset(cstemp, 0, 64); sprintf(cstemp, "[%d bytes (%d bytes unused)] ", head.size, head.size - snrm.Read(localptr, head)); localptr += (head.size - 8);//8 for the already added header //stats += cstemp; //stats += "\n"; /*memset(cstemp, 0, 64); sprintf(cstemp, " @+ BackOffset: %d, FrontOffset: %d, OnlineOffset: %d, ", snrm.back_offset, snrm.front_offset, snrm.online_offset); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ PostListOffset: %d, PreListOffset: %d, ", snrm.back_offset, snrm.front_offset, snrm.online_offset); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ Plane_Normal: (%f, %f, %f)", snrm.plane_normal.x, snrm.plane_normal.y, snrm.plane_normal.z); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ Plane_Point: (%f, %f, %f)", snrm.plane_point.x, snrm.plane_point.y, snrm.plane_point.z); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ BoundBoxMin: (%f, %f, %f)", snrm.min_bounding_box_point.x, snrm.min_bounding_box_point.y, snrm.min_bounding_box_point.z); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ BoundBoxMax: (%f, %f, %f)", snrm.max_bounding_box_point.x, snrm.max_bounding_box_point.y, snrm.max_bounding_box_point.z); stats += cstemp; stats += "\n"; stats += "\n";*/ Add_SortNorm(snrm); break; case 5: //stats += "BOUNDBOX "; memset(cstemp, 0, 64); sprintf(cstemp, "[%d bytes (%d bytes unused)]", head.size, head.size - bnd.Read(localptr, head)); localptr += (head.size - 8);//8 for the already added header /*stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ BoundBoxMin: (%f, %f, %f)", bnd.min_point.x, bnd.min_point.y, bnd.min_point.z); stats += cstemp; stats += "\n"; memset(cstemp, 0, 64); sprintf(cstemp, " @+ BoundBoxMax: (%f, %f, %f)", bnd.max_point.x, bnd.max_point.y, bnd.max_point.z); stats += cstemp; stats += "\n"; stats += "\n";*/ Add_BoundBox(bnd); break; default: stats += "WARNING: Encountered UNKNOWN: Check data format and/or pointer alignment!\n"; go = false; break; } } return stats; }
bool PCS_Model::PMFObj_to_POFObj2(int src_num, OBJ2 &dst, bool &bsp_compiled, float& model_radius) { pcs_sobj &src = subobjects[src_num]; dst.submodel_parent = src.parent_sobj; dst.offset = POFTranslate(src.offset); dst.geometric_center = POFTranslate(src.geometric_center); dst.submodel_name = APStoString(src.name); dst.properties = APStoString(src.properties); switch (src.movement_type) { case ROTATE: dst.movement_type = 1; break; default: dst.movement_type = -1; } switch (src.movement_axis) { case MV_X: dst.movement_axis = 0; break; case MV_Z: dst.movement_axis = 1; break; case MV_Y: dst.movement_axis = 2; break; default: dst.movement_axis = -1; } dst.reserved = 0; if(!can_bsp_cache || bsp_cache[src_num].changed) { // convert them to POF axis std::vector<pcs_polygon> clean_list = src.polygons; for (size_t i = 0; i < clean_list.size(); i++) { clean_list[i].norm = POFTranslate(clean_list[i].norm); for (size_t j = 0; j < clean_list[i].verts.size(); j++) { clean_list[i].verts[j].point = POFTranslate(clean_list[i].verts[j].point); clean_list[i].verts[j].norm = POFTranslate(clean_list[i].verts[j].norm); } clean_list[i].centeroid = PolygonCenter(clean_list[i]); } // BSP Compilation! // assemble points list std::vector<bsp_vert> points_list; std::vector<vector3d> pnts; std::unordered_map<vector3d, int> point_to_index; std::unordered_map<vector3d, int> normal_to_index; for (size_t i = 0; i < pnts.size(); i++) { point_to_index.insert(std::make_pair(pnts[i], i)); } bsp_vert temp; points_list.reserve(clean_list.size()); for (size_t i = 0; i < clean_list.size(); i++) { for (size_t j = 0; j < clean_list[i].verts.size(); j++) { auto point = point_to_index.find(clean_list[i].verts[j].point); if (point == point_to_index.end()) { point_to_index.insert(std::make_pair(clean_list[i].verts[j].point, points_list.size())); points_list.emplace_back(); points_list.back().point = clean_list[i].verts[j].point; pnts.push_back(points_list.back().point); } auto normal = normal_to_index.find(clean_list[i].verts[j].norm); if (normal == normal_to_index.end()) { points_list[normal_to_index.size() / 128].norms.push_back(clean_list[i].verts[j].norm); normal_to_index.insert(std::make_pair(clean_list[i].verts[j].norm, normal_to_index.size())); } } } // create our defpoints BSP_DefPoints points; MakeDefPoints(points, points_list); vector3d AvgNormal; // create tree std::unique_ptr<bsp_tree_node> root = MakeTree(clean_list, dst.bounding_box_max_point, dst.bounding_box_min_point); // allocate buffer and write the defpoints dst.bsp_data.resize(points.head.size + CalculateTreeSize(root.get(), clean_list)); if (points.Write(&dst.bsp_data.front()) != points.head.size) return false; // calculation error //std::ofstream bsp_debug("c:\\bsp.txt"); //DebugPrintTree(root, bsp_debug); // pack the tree int error_flags = 0; PackTreeInBSP(root.get(), points.head.size, &dst.bsp_data.front(), clean_list, normal_to_index, point_to_index, points, dst.geometric_center, dst.bsp_data.size(), error_flags); // we got errors! if (error_flags != BSP_NOERRORS) return false; // update the bsp_compiled to be true bsp_compiled = true; // update the BSP cache with the new result if (can_bsp_cache) { // clear the saved - stale cache bsp_cache[src_num].decache(); bsp_cache[src_num].bsp_data = dst.bsp_data; bsp_cache[src_num].changed = false; } } else // Used cached copy! { dst.bsp_data = bsp_cache[src_num].bsp_data; } dst.radius = 0.0f; dst.bounding_box_max_point = vector3d(FLT_MIN, FLT_MIN, FLT_MIN); dst.bounding_box_min_point = vector3d(FLT_MAX, FLT_MAX, FLT_MAX); vector3d global_offset(OffsetFromParent(src_num)); for(unsigned int i = 0; i<src.polygons.size(); i++){ for(unsigned int j = 0; j<src.polygons[i].verts.size(); j++){ ExpandBoundingBoxes(dst.bounding_box_max_point, dst.bounding_box_min_point, src.polygons[i].verts[j].point); float norm = Magnitude(src.polygons[i].verts[j].point); if (norm > dst.radius) { dst.radius = norm; } float global_norm = Magnitude(src.polygons[i].verts[j].point + global_offset); if (global_norm > model_radius) { model_radius = global_norm; } } } if (dst.radius == 0.0f) { dst.bounding_box_max_point = vector3d(); dst.bounding_box_min_point = vector3d(); } if (src.radius_overridden) { dst.radius = src.radius_override; } if (src.bounding_box_min_point_overridden) { dst.bounding_box_min_point = src.bounding_box_min_point_override; } if (src.bounding_box_max_point_overridden) { dst.bounding_box_max_point = src.bounding_box_max_point_override; } POFTranslateBoundingBoxes(dst.bounding_box_min_point, dst.bounding_box_max_point); return true; }