ACE3/extensions/common/p3d/compressed.hpp
2016-05-30 18:37:03 +02:00

171 lines
6.5 KiB
C++

#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<uint8_t[]> _data;
#else
std::unique_ptr<uint8_t[]> _data;
#endif
};
template<typename T>
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<T> data;
bool flag;
};
template<typename T>
class compressed : public compressed_base<T> {
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<vector3<float>> : public compressed_base<vector3<float>>{
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<float> 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<float>(ptr+x));
}
}
} else {
for (int x = 0; x < size; x++) {
data.push_back(ace::vector3<float>(stream_));
}
}
}
}
ace::vector3<float> 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<float>(x * scaleFactor, y * scaleFactor, z * scaleFactor);
}
};
template<>
class compressed<pair<float>> : public compressed_base<pair<float>>{
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<float> 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<float>(ptr + x));
}
}
else {
for (int x = 0; x < size; x++) {
data.push_back(ace::pair<float>(stream_));
}
}
}
}
};
}
}