int CalculateTreeSize(bsp_tree_node* root, std::vector<pcs_polygon> &polygons) { if (root == NULL) return 8; // size of an BSP::EOF int ret_size = 0; switch(root->Type) { case POLY: // Size is BBOX (32 bytes) + Poly (variable on type and count) + EOF ( 8 bytes) ret_size += 32; for(unsigned int i = 0; i<root->poly_num.size(); i++){ if (polygons[root->poly_num[i]].texture_id == -1) ret_size += 44 + 4 * polygons[root->poly_num[i]].verts.size();// Fplatpoly else ret_size += 44 + 12 * polygons[root->poly_num[i]].verts.size();//Tmappoly } ret_size += 8; root->counted = true; return ret_size; default: //SPLIT root->counted = true; return 104 + CalculateTreeSize(root->front.get(), polygons) + CalculateTreeSize(root->back.get(), polygons); // 80 + 3*8 bytes for pre/post/onlist EOFs } return 0; }
double ZopfliCalculateBlockSize(const ZopfliLZ77Store* lz77, size_t lstart, size_t lend, int btype) { unsigned ll_lengths[ZOPFLI_NUM_LL]; unsigned d_lengths[ZOPFLI_NUM_D]; double result = 3; /* bfinal and btype bits */ if (btype == 0) { size_t length = ZopfliLZ77GetByteRange(lz77, lstart, lend); size_t rem = length % 65535; size_t blocks = length / 65535 + (rem ? 1 : 0); /* An uncompressed block must actually be split into multiple blocks if it's larger than 65535 bytes long. Eeach block header is 5 bytes: 3 bits, padding, LEN and NLEN (potential less padding for first one ignored). */ return blocks * 5 * 8 + length * 8; } if (btype == 1) { GetFixedTree(ll_lengths, d_lengths); } else { GetDynamicLengths(lz77, lstart, lend, ll_lengths, d_lengths); result += CalculateTreeSize(ll_lengths, d_lengths); } result += CalculateBlockSymbolSize( ll_lengths, d_lengths, lz77, lstart, lend); return result; }
double ZopfliCalculateBlockSize(const unsigned short* litlens, const unsigned short* dists, size_t lstart, size_t lend, int btype) { size_t ll_counts[288]; size_t d_counts[32]; unsigned ll_lengths[288]; unsigned d_lengths[32]; double result = 3; /*bfinal and btype bits*/ assert(btype == 1 || btype == 2); /* This is not for uncompressed blocks. */ if(btype == 1) { GetFixedTree(ll_lengths, d_lengths); } else { ZopfliLZ77Counts(litlens, dists, lstart, lend, ll_counts, d_counts); ZopfliCalculateBitLengths(ll_counts, 288, 15, ll_lengths); ZopfliCalculateBitLengths(d_counts, 32, 15, d_lengths); PatchDistanceCodesForBuggyDecoders(d_lengths); result += CalculateTreeSize(ll_lengths, d_lengths, ll_counts, d_counts); } result += CalculateBlockSymbolSize( ll_lengths, d_lengths, litlens, dists, lstart, lend); return result; }
/* Tries out OptimizeHuffmanForRle for this block, if the result is smaller, uses it, otherwise keeps the original. Returns size of encoded tree and data in bits, not including the 3-bit block header. */ static double TryOptimizeHuffmanForRle( const ZopfliLZ77Store* lz77, size_t lstart, size_t lend, const size_t* ll_counts, const size_t* d_counts, unsigned* ll_lengths, unsigned* d_lengths) { size_t ll_counts2[ZOPFLI_NUM_LL]; size_t d_counts2[ZOPFLI_NUM_D]; unsigned ll_lengths2[ZOPFLI_NUM_LL]; unsigned d_lengths2[ZOPFLI_NUM_D]; double treesize; double datasize; double treesize2; double datasize2; treesize = CalculateTreeSize(ll_lengths, d_lengths); datasize = CalculateBlockSymbolSizeGivenCounts(ll_counts, d_counts, ll_lengths, d_lengths, lz77, lstart, lend); memcpy(ll_counts2, ll_counts, sizeof(ll_counts2)); memcpy(d_counts2, d_counts, sizeof(d_counts2)); OptimizeHuffmanForRle(ZOPFLI_NUM_LL, ll_counts2); OptimizeHuffmanForRle(ZOPFLI_NUM_D, d_counts2); ZopfliCalculateBitLengths(ll_counts2, ZOPFLI_NUM_LL, 15, ll_lengths2); ZopfliCalculateBitLengths(d_counts2, ZOPFLI_NUM_D, 15, d_lengths2); PatchDistanceCodesForBuggyDecoders(d_lengths2); treesize2 = CalculateTreeSize(ll_lengths2, d_lengths2); datasize2 = CalculateBlockSymbolSizeGivenCounts(ll_counts, d_counts, ll_lengths2, d_lengths2, lz77, lstart, lend); if (treesize2 + datasize2 < treesize + datasize) { memcpy(ll_lengths, ll_lengths2, sizeof(ll_lengths2)); memcpy(d_lengths, d_lengths2, sizeof(d_lengths2)); return treesize2 + datasize2; } return treesize + datasize; }
double Population::CalculateParsimonyCoefficient() { double covariance = 0; double variance = 0; CalculateRawFitness(); CalculateTreeSize(); /* for (size_t i = 0; i < pop_.size(); ++i) { double cov = static_cast<double>((pop_[i].GetTreeSize() - avg_tree_)); double var = cov * cov; cov *= (pop_[i].GetFitness() - avg_fitness_); covariance += (cov / pop_.size()); variance += (var / pop_.size()); } return covariance / variance; */ return 1.0f; }
double ZopfliCalculateBlockSize(const unsigned short* litlens, const unsigned short* dists, size_t lstart, size_t lend, int btype) { unsigned ll_lengths[288]; unsigned d_lengths[32]; double result = 3; /* bfinal and btype bits */ assert(btype == 1 || btype == 2); /* This is not for uncompressed blocks. */ if(btype == 1) { GetFixedTree(ll_lengths, d_lengths); } else { GetDynamicLengths(litlens, dists, lstart, lend, ll_lengths, d_lengths); result += CalculateTreeSize(ll_lengths, d_lengths); } result += CalculateBlockSymbolSize( ll_lengths, d_lengths, litlens, dists, lstart, lend); return result; }
int PackTreeInBSP(bsp_tree_node* root, int offset, char *buffer, std::vector<pcs_polygon> &polygons, std::unordered_map<vector3d, int> &norms, std::unordered_map<vector3d, int> &verts, BSP_DefPoints &dpnts, vector3d geo_center, int buffsize, int &error_flags) { // ----------- error detection --------------- // abort if error detected if (error_flags != BSP_NOERRORS) return 0; // we're going to write off the end of the buffer gauranteed (smallest element is EOF - 8 bytes if (offset >= buffsize-7) { error_flags |= BSP_PACK_PREOVERFLOW; return 0; } // either we're written this node already, or it didn't get counted in size calculation.. this is bad, skip if (root != NULL && root->used == true) { error_flags |= BSP_PACK_DOUBLEUSE; return 0; } if (root != NULL && root->counted == false) { error_flags |= BSP_PACK_UNCOUNTED; return 0; } // ----------- finish error detection --------------- int size = 0; BSP_BlockHeader EndOfFile; EndOfFile.id = 0; EndOfFile.size = 0; BSP_BoundBox Bounding; Bounding.head.id = 5; Bounding.head.size = Bounding.MySize(); BSP_TmapPoly tpoly; BSP_FlatPoly fpoly; BSP_SortNorm snorm; if (root == NULL) { EndOfFile.Write(buffer+offset); return 8; } switch(root->Type) { case POLY: // write BBOX Bounding.max_point = root->bound_max; Bounding.min_point = root->bound_min; Bounding.Write(buffer+offset+size); size += Bounding.MySize(); if (offset+CalculateTreeSize(root, polygons) > buffsize) { error_flags |= BSP_PACK_PREPOLYOVERFLOW; return 0; } // Size is BBOX (32 bytes) + Poly (variable on type and count) + EOF ( 8 bytes) // write POLY for(unsigned int i = 0; i<root->poly_num.size(); i++){ if (polygons[root->poly_num[i]].texture_id == -1) { MakeFlatPoly(fpoly, polygons[root->poly_num[i]], norms, verts, dpnts); fpoly.Write(buffer+offset+size); size += fpoly.MySize(); } else { MakeTmapPoly(tpoly, polygons[root->poly_num[i]], norms, verts, dpnts); tpoly.Write(buffer+offset+size); size += tpoly.MySize(); } } // write EOF EndOfFile.Write(buffer+offset+size); size += EndOfFile.MySize(); root->used = true; if (offset+size > buffsize) { error_flags |= BSP_PACK_POLYOVERFLOW; } return size; default: //SPLIT size = 80; memset((char*)&snorm, 0, sizeof(BSP_SortNorm)); snorm.head.id = 4; snorm.head.size = snorm.MySize(); snorm.plane_point = root->point; snorm.plane_normal = root->normal; snorm.max_bounding_box_point = root->bound_max; snorm.min_bounding_box_point = root->bound_min; if (offset+CalculateTreeSize(root, polygons) > buffsize) { error_flags |= BSP_PACK_PRESPLITOVERFLOW; return 0; } snorm.prelist_offset = size; size += PackTreeInBSP(NULL, offset+size, buffer, polygons, norms, verts, dpnts, geo_center, buffsize, error_flags); snorm.postlist_offset = size; size += PackTreeInBSP(NULL, offset + size, buffer, polygons, norms, verts, dpnts, geo_center, buffsize, error_flags); snorm.online_offset = size; size += PackTreeInBSP(NULL, offset + size, buffer, polygons, norms, verts, dpnts, geo_center, buffsize, error_flags); snorm.front_offset = size; size += PackTreeInBSP(root->front.get(), offset+size, buffer, polygons, norms, verts, dpnts, geo_center, buffsize, error_flags); snorm.back_offset = size; size += PackTreeInBSP(root->back.get(), offset+size, buffer, polygons, norms, verts, dpnts, geo_center, buffsize, error_flags); snorm.Write(buffer+offset); // write a trailing BSP::EOF to make ourselves safe //EndOfFile.Write(buffer+offset+size); //size += EndOfFile.MySize(); root->used = true; if (offset+size > buffsize) { error_flags |= BSP_PACK_SPLITOVERFLOW; } return size; } return 0; }
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; }