#pragma once #include "shared.hpp" #include "vector.hpp" #include "read_helpers.hpp" namespace ace { namespace p3d { class _compressed_base { protected: int _mikero_lzo1x_decompress_safe(const uint8_t*, uint8_t*, uint32_t); int _decompress_safe(std::istream &, uint32_t); #if _MSC_VER == 1800 std::shared_ptr _data; #else std::unique_ptr _data; #endif }; template class compressed_base : public _compressed_base { public: compressed_base() : fill(false), size(0), flag(0) {} T & operator[] (const int index) { return data[index]; } uint32_t size; bool fill; std::vector data; bool flag; }; template class compressed : public compressed_base { public: compressed() { } compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, uint32_t version = 68) { stream_.read((char *)&this->size, sizeof(uint32_t)); // if(version <) if(fill_) READ_BOOL(this->fill); assert(this->size < 4095 * 10); if (this->size > 0) { if (this->fill) { T val; stream_.read((char *)&val, sizeof(T)); for (int x = 0; x < this->size; x++) { this->data.push_back(val); } } else { if (version >= 64 && compressed_) { READ_BOOL(this->flag); } if ( (this->size * sizeof(T) >= 1024 && compressed_ && version < 64) || (this->flag && compressed_)) { int32_t result = this->_decompress_safe(stream_, this->size * sizeof(T)); assert(result > 0); T * ptr = (T *)(this->_data.get()); this->data.assign(ptr, ptr + this->size ); } else { for (int x = 0; x < this->size; x++) { T val; stream_.read((char *)&val, sizeof(T)); this->data.push_back(val); } } } } } }; template<> class compressed> : public compressed_base>{ public: compressed() {} compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, bool xyzCompressed = false, uint32_t version = 68) { stream_.read((char *)&size, sizeof(uint32_t)); if(fill_) READ_BOOL(fill); if (fill) { ace::vector3 val(stream_); for (int x = 0; x < size; x++) { data.push_back(val); } } else { if (version >= 64) { READ_BOOL(flag); } if ((size * sizeof(float)*3 >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { if (xyzCompressed) { int32_t result = _decompress_safe(stream_, size * sizeof(float)); uint32_t * ptr = (uint32_t *)(_data.get()); for (int x = 0; x < size; x++) { uint32_t value = ptr[x]; data.push_back(decode_xyz(value)); } } else { int32_t result = _decompress_safe(stream_, size * sizeof(float) * 3); float * ptr = (float *)(_data.get()); for (int x = 0; x < size*3; x+=3) { data.push_back(ace::vector3(ptr+x)); } } } else { for (int x = 0; x < size; x++) { data.push_back(ace::vector3(stream_)); } } } } ace::vector3 decode_xyz(uint32_t CompressedXYZ) { double scaleFactor = -1.0 / 511; int x = CompressedXYZ & 0x3FF; int y = (CompressedXYZ >> 10) & 0x3FF; int z = (CompressedXYZ >> 20) & 0x3FF; if (x > 511) x -= 1024; if (y > 511) y -= 1024; if (z > 511) z -= 1024; return ace::vector3(x * scaleFactor, y * scaleFactor, z * scaleFactor); } }; template<> class compressed> : public compressed_base>{ public: compressed() {} compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, uint32_t version = 68) { stream_.read((char *)&size, sizeof(uint32_t)); if (fill_) READ_BOOL(fill); if (fill) { ace::pair val(stream_); for (int x = 0; x < size; x++) { data.push_back(val); } } else { if (version >= 64) { READ_BOOL(flag); } if ((size * sizeof(float)*2 >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { int32_t result = _decompress_safe(stream_, size * sizeof(float) * 2); float * ptr = (float *)(_data.get()); for (int x = 0; x < size * 2; x += 2) { data.push_back(ace::pair(ptr + x)); } } else { for (int x = 0; x < size; x++) { data.push_back(ace::pair(stream_)); } } } } }; } }