mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Merge pull request #4135 from ey6es/master
Back to JPG compression for heightfield colors.
This commit is contained in:
commit
4112acc382
8 changed files with 68 additions and 81 deletions
|
@ -311,7 +311,7 @@ MetavoxelPersister::MetavoxelPersister(MetavoxelServer* server) :
|
|||
const char* SAVE_FILE = "/resources/metavoxels.dat";
|
||||
|
||||
const int FILE_MAGIC = 0xDADAFACE;
|
||||
const int FILE_VERSION = 3;
|
||||
const int FILE_VERSION = 4;
|
||||
|
||||
void MetavoxelPersister::load() {
|
||||
QString path = QCoreApplication::applicationDirPath() + SAVE_FILE;
|
||||
|
|
|
@ -22,7 +22,8 @@ varying vec4 alphaValues;
|
|||
|
||||
void main(void) {
|
||||
// blend the splat textures
|
||||
gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
|
||||
gl_FragColor = vec4(gl_Color.rgb, step(1.0, gl_Color.a + 1.0 / 512.0)) *
|
||||
(texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
|
||||
texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y +
|
||||
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
|
||||
texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w);
|
||||
|
|
|
@ -2432,12 +2432,13 @@ void MappedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
|
|||
}
|
||||
|
||||
QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||
bool reread = (object != NULL);
|
||||
if (!object && _metaObject) {
|
||||
object = _metaObject->newInstance();
|
||||
}
|
||||
foreach (const StreamerPropertyPair& property, _properties) {
|
||||
QVariant value = property.first->read(in);
|
||||
if (property.second.isValid() && object) {
|
||||
if (property.second.isValid() && object && !reread) {
|
||||
property.second.write(object, value);
|
||||
}
|
||||
}
|
||||
|
@ -2445,6 +2446,7 @@ QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
|||
}
|
||||
|
||||
QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||
bool reread = (object != NULL);
|
||||
if (!object && _metaObject) {
|
||||
object = _metaObject->newInstance();
|
||||
}
|
||||
|
@ -2452,7 +2454,7 @@ QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* refere
|
|||
QVariant value;
|
||||
property.first->readDelta(in, value, (property.second.isValid() && reference &&
|
||||
reference->metaObject() == _metaObject) ? property.second.read(reference) : QVariant());
|
||||
if (property.second.isValid() && object) {
|
||||
if (property.second.isValid() && object && !reread) {
|
||||
property.second.write(object, value);
|
||||
}
|
||||
}
|
||||
|
@ -2475,13 +2477,13 @@ void SharedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
|
|||
|
||||
QObject* SharedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||
QObject* result = MappedObjectStreamer::read(in, object);
|
||||
static_cast<SharedObject*>(result)->readExtra(in);
|
||||
static_cast<SharedObject*>(result)->readExtra(in, object != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||
QObject* result = MappedObjectStreamer::readRawDelta(in, reference, object);
|
||||
static_cast<SharedObject*>(result)->readExtraDelta(in, static_cast<const SharedObject*>(reference));
|
||||
static_cast<SharedObject*>(result)->readExtraDelta(in, static_cast<const SharedObject*>(reference), object != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2592,6 +2594,7 @@ void GenericObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
|
|||
}
|
||||
|
||||
QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||
bool reread = (object != NULL);
|
||||
if (!object) {
|
||||
object = new GenericSharedObject(_weakSelf);
|
||||
}
|
||||
|
@ -2599,11 +2602,14 @@ QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
|||
foreach (const StreamerNamePair& property, _properties) {
|
||||
values.append(property.first->read(in));
|
||||
}
|
||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||
if (!reread) {
|
||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||
bool reread = (object != NULL);
|
||||
if (!object) {
|
||||
object = new GenericSharedObject(_weakSelf);
|
||||
}
|
||||
|
@ -2615,7 +2621,9 @@ QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* refer
|
|||
static_cast<const GenericSharedObject*>(reference)->getValues().at(i) : QVariant());
|
||||
values.append(value);
|
||||
}
|
||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||
if (!reread) {
|
||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ void SharedObject::writeExtra(Bitstream& out) const {
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
void SharedObject::readExtra(Bitstream& in) {
|
||||
void SharedObject::readExtra(Bitstream& in, bool reread) {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ void SharedObject::writeExtraDelta(Bitstream& out, const SharedObject* reference
|
|||
// nothing by default
|
||||
}
|
||||
|
||||
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) {
|
||||
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) {
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
|
|
|
@ -84,13 +84,15 @@ public:
|
|||
virtual void writeExtra(Bitstream& out) const;
|
||||
|
||||
/// Reads the non-property contents of this object from the specified stream.
|
||||
virtual void readExtra(Bitstream& in);
|
||||
/// \param reread if true, reread the contents from the stream but don't reapply them
|
||||
virtual void readExtra(Bitstream& in, bool reread = false);
|
||||
|
||||
/// Writes the delta-encoded non-property contents of this object to the specified stream.
|
||||
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
|
||||
|
||||
/// Reads the delta-encoded non-property contents of this object from the specified stream.
|
||||
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
|
||||
/// \param reread if true, reread the contents from the stream but don't reapply them
|
||||
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread = false);
|
||||
|
||||
/// Writes the subdivision of the contents of this object (preceeded by a
|
||||
/// reference to the object itself) to the specified stream if necessary.
|
||||
|
|
|
@ -681,41 +681,17 @@ void HeightfieldHeightEditor::clear() {
|
|||
}
|
||||
|
||||
static QByteArray encodeHeightfieldColor(int offsetX, int offsetY, int width, int height, const QByteArray& contents) {
|
||||
QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE + contents.size(), 0);
|
||||
QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0);
|
||||
qint32* header = (qint32*)inflated.data();
|
||||
*header++ = offsetX;
|
||||
*header++ = offsetY;
|
||||
*header++ = width;
|
||||
*header++ = height;
|
||||
if (!contents.isEmpty()) {
|
||||
// encode with Paeth filter (see http://en.wikipedia.org/wiki/Portable_Network_Graphics#Filtering)
|
||||
const uchar* src = (const uchar*)contents.constData();
|
||||
uchar* dest = (uchar*)inflated.data() + HEIGHTFIELD_DATA_HEADER_SIZE;
|
||||
*dest++ = *src++;
|
||||
*dest++ = *src++;
|
||||
*dest++ = *src++;
|
||||
int stride = width * DataBlock::COLOR_BYTES;
|
||||
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
|
||||
*dest = *src - src[-DataBlock::COLOR_BYTES];
|
||||
}
|
||||
for (int y = 1; y < height; y++) {
|
||||
*dest++ = *src - src[-stride];
|
||||
src++;
|
||||
*dest++ = *src - src[-stride];
|
||||
src++;
|
||||
*dest++ = *src - src[-stride];
|
||||
src++;
|
||||
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
|
||||
int a = src[-DataBlock::COLOR_BYTES];
|
||||
int b = src[-stride];
|
||||
int c = src[-stride - DataBlock::COLOR_BYTES];
|
||||
int p = a + b - c;
|
||||
int ad = abs(a - p);
|
||||
int bd = abs(b - p);
|
||||
int cd = abs(c - p);
|
||||
*dest = *src - (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c));
|
||||
}
|
||||
}
|
||||
QBuffer buffer(&inflated);
|
||||
buffer.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||
QImage((const uchar*)contents.constData(), width, height, width * DataBlock::COLOR_BYTES,
|
||||
QImage::Format_RGB888).save(&buffer, "JPG");
|
||||
}
|
||||
return qCompress(inflated);
|
||||
}
|
||||
|
@ -727,35 +703,19 @@ static QByteArray decodeHeightfieldColor(const QByteArray& encoded, int& offsetX
|
|||
offsetY = *header++;
|
||||
width = *header++;
|
||||
height = *header++;
|
||||
QByteArray contents(inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE, 0);
|
||||
if (!contents.isEmpty()) {
|
||||
const uchar* src = (const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE;
|
||||
uchar* dest = (uchar*)contents.data();
|
||||
*dest++ = *src++;
|
||||
*dest++ = *src++;
|
||||
*dest++ = *src++;
|
||||
int stride = width * DataBlock::COLOR_BYTES;
|
||||
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
|
||||
*dest = *src + dest[-DataBlock::COLOR_BYTES];
|
||||
}
|
||||
for (int y = 1; y < height; y++) {
|
||||
*dest = (*src++) + dest[-stride];
|
||||
dest++;
|
||||
*dest = (*src++) + dest[-stride];
|
||||
dest++;
|
||||
*dest = (*src++) + dest[-stride];
|
||||
dest++;
|
||||
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
|
||||
int a = dest[-DataBlock::COLOR_BYTES];
|
||||
int b = dest[-stride];
|
||||
int c = dest[-stride - DataBlock::COLOR_BYTES];
|
||||
int p = a + b - c;
|
||||
int ad = abs(a - p);
|
||||
int bd = abs(b - p);
|
||||
int cd = abs(c - p);
|
||||
*dest = *src + (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c));
|
||||
}
|
||||
}
|
||||
int payloadSize = inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE;
|
||||
if (payloadSize == 0) {
|
||||
return QByteArray();
|
||||
}
|
||||
QImage image = QImage::fromData((const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE, payloadSize, "JPG");
|
||||
if (image.format() != QImage::Format_RGB888) {
|
||||
image = image.convertToFormat(QImage::Format_RGB888);
|
||||
}
|
||||
QByteArray contents(width * height * DataBlock::COLOR_BYTES, 0);
|
||||
char* dest = contents.data();
|
||||
int stride = width * DataBlock::COLOR_BYTES;
|
||||
for (int y = 0; y < height; y++, dest += stride) {
|
||||
memcpy(dest, image.constScanLine(y), stride);
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
@ -3718,9 +3678,18 @@ void Heightfield::writeExtra(Bitstream& out) const {
|
|||
_root->write(state);
|
||||
}
|
||||
|
||||
void Heightfield::readExtra(Bitstream& in) {
|
||||
void Heightfield::readExtra(Bitstream& in, bool reread) {
|
||||
if (getWillBeVoxelized()) {
|
||||
in >> _height >> _color >> _material >> _stack;
|
||||
if (reread) {
|
||||
HeightfieldHeightPointer height;
|
||||
HeightfieldColorPointer color;
|
||||
HeightfieldMaterialPointer material;
|
||||
HeightfieldStackPointer stack;
|
||||
in >> height >> color >> material >> stack;
|
||||
|
||||
} else {
|
||||
in >> _height >> _color >> _material >> _stack;
|
||||
}
|
||||
return;
|
||||
}
|
||||
MetavoxelLOD lod;
|
||||
|
@ -3732,7 +3701,9 @@ void Heightfield::readExtra(Bitstream& in) {
|
|||
|
||||
HeightfieldNodePointer root(new HeightfieldNode());
|
||||
root->read(state);
|
||||
setRoot(root);
|
||||
if (!reread) {
|
||||
setRoot(root);
|
||||
}
|
||||
}
|
||||
|
||||
void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const {
|
||||
|
@ -3756,7 +3727,7 @@ void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference)
|
|||
}
|
||||
}
|
||||
|
||||
void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) {
|
||||
void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) {
|
||||
MetavoxelLOD lod, referenceLOD;
|
||||
if (in.getContext()) {
|
||||
MetavoxelStreamBase* base = static_cast<MetavoxelStreamBase*>(in.getContext());
|
||||
|
@ -3766,16 +3737,21 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) {
|
|||
HeightfieldStreamBase base = { in, lod, referenceLOD };
|
||||
HeightfieldStreamState state = { base, glm::vec2(), 1.0f };
|
||||
|
||||
setRoot(static_cast<const Heightfield*>(reference)->getRoot());
|
||||
bool changed;
|
||||
in >> changed;
|
||||
if (changed) {
|
||||
HeightfieldNodePointer root(new HeightfieldNode());
|
||||
root->readDelta(static_cast<const Heightfield*>(reference)->getRoot(), state);
|
||||
setRoot(root);
|
||||
|
||||
if (!reread) {
|
||||
setRoot(root);
|
||||
}
|
||||
} else if (state.becameSubdividedOrCollapsed()) {
|
||||
setRoot(HeightfieldNodePointer(_root->readSubdivision(state)));
|
||||
HeightfieldNodePointer root(_root->readSubdivision(state));
|
||||
if (!reread) {
|
||||
setRoot(root);
|
||||
}
|
||||
} else if (!reread) {
|
||||
setRoot(static_cast<const Heightfield*>(reference)->getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -820,9 +820,9 @@ public:
|
|||
virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal);
|
||||
|
||||
virtual void writeExtra(Bitstream& out) const;
|
||||
virtual void readExtra(Bitstream& in);
|
||||
virtual void readExtra(Bitstream& in, bool reread);
|
||||
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
|
||||
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
|
||||
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread);
|
||||
virtual void maybeWriteSubdivision(Bitstream& out);
|
||||
virtual SharedObject* readSubdivision(Bitstream& in);
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
case PacketTypeAudioStreamStats:
|
||||
return 1;
|
||||
case PacketTypeMetavoxelData:
|
||||
return 11;
|
||||
return 12;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue