mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 16:41:02 +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 char* SAVE_FILE = "/resources/metavoxels.dat";
|
||||||
|
|
||||||
const int FILE_MAGIC = 0xDADAFACE;
|
const int FILE_MAGIC = 0xDADAFACE;
|
||||||
const int FILE_VERSION = 3;
|
const int FILE_VERSION = 4;
|
||||||
|
|
||||||
void MetavoxelPersister::load() {
|
void MetavoxelPersister::load() {
|
||||||
QString path = QCoreApplication::applicationDirPath() + SAVE_FILE;
|
QString path = QCoreApplication::applicationDirPath() + SAVE_FILE;
|
||||||
|
|
|
@ -22,7 +22,8 @@ varying vec4 alphaValues;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
// blend the splat textures
|
// 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[1], gl_TexCoord[1].st) * alphaValues.y +
|
||||||
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
|
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
|
||||||
texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w);
|
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 {
|
QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
|
bool reread = (object != NULL);
|
||||||
if (!object && _metaObject) {
|
if (!object && _metaObject) {
|
||||||
object = _metaObject->newInstance();
|
object = _metaObject->newInstance();
|
||||||
}
|
}
|
||||||
foreach (const StreamerPropertyPair& property, _properties) {
|
foreach (const StreamerPropertyPair& property, _properties) {
|
||||||
QVariant value = property.first->read(in);
|
QVariant value = property.first->read(in);
|
||||||
if (property.second.isValid() && object) {
|
if (property.second.isValid() && object && !reread) {
|
||||||
property.second.write(object, value);
|
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 {
|
QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||||
|
bool reread = (object != NULL);
|
||||||
if (!object && _metaObject) {
|
if (!object && _metaObject) {
|
||||||
object = _metaObject->newInstance();
|
object = _metaObject->newInstance();
|
||||||
}
|
}
|
||||||
|
@ -2452,7 +2454,7 @@ QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* refere
|
||||||
QVariant value;
|
QVariant value;
|
||||||
property.first->readDelta(in, value, (property.second.isValid() && reference &&
|
property.first->readDelta(in, value, (property.second.isValid() && reference &&
|
||||||
reference->metaObject() == _metaObject) ? property.second.read(reference) : QVariant());
|
reference->metaObject() == _metaObject) ? property.second.read(reference) : QVariant());
|
||||||
if (property.second.isValid() && object) {
|
if (property.second.isValid() && object && !reread) {
|
||||||
property.second.write(object, value);
|
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* SharedObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
QObject* result = MappedObjectStreamer::read(in, object);
|
QObject* result = MappedObjectStreamer::read(in, object);
|
||||||
static_cast<SharedObject*>(result)->readExtra(in);
|
static_cast<SharedObject*>(result)->readExtra(in, object != NULL);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||||
QObject* result = MappedObjectStreamer::readRawDelta(in, reference, object);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2592,6 +2594,7 @@ void GenericObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
|
bool reread = (object != NULL);
|
||||||
if (!object) {
|
if (!object) {
|
||||||
object = new GenericSharedObject(_weakSelf);
|
object = new GenericSharedObject(_weakSelf);
|
||||||
}
|
}
|
||||||
|
@ -2599,11 +2602,14 @@ QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
|
||||||
foreach (const StreamerNamePair& property, _properties) {
|
foreach (const StreamerNamePair& property, _properties) {
|
||||||
values.append(property.first->read(in));
|
values.append(property.first->read(in));
|
||||||
}
|
}
|
||||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
if (!reread) {
|
||||||
|
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||||
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
|
||||||
|
bool reread = (object != NULL);
|
||||||
if (!object) {
|
if (!object) {
|
||||||
object = new GenericSharedObject(_weakSelf);
|
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());
|
static_cast<const GenericSharedObject*>(reference)->getValues().at(i) : QVariant());
|
||||||
values.append(value);
|
values.append(value);
|
||||||
}
|
}
|
||||||
static_cast<GenericSharedObject*>(object)->setValues(values);
|
if (!reread) {
|
||||||
|
static_cast<GenericSharedObject*>(object)->setValues(values);
|
||||||
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ void SharedObject::writeExtra(Bitstream& out) const {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObject::readExtra(Bitstream& in) {
|
void SharedObject::readExtra(Bitstream& in, bool reread) {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ void SharedObject::writeExtraDelta(Bitstream& out, const SharedObject* reference
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) {
|
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,13 +84,15 @@ public:
|
||||||
virtual void writeExtra(Bitstream& out) const;
|
virtual void writeExtra(Bitstream& out) const;
|
||||||
|
|
||||||
/// Reads the non-property contents of this object from the specified stream.
|
/// 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.
|
/// Writes the delta-encoded non-property contents of this object to the specified stream.
|
||||||
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
|
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
|
||||||
|
|
||||||
/// Reads the delta-encoded non-property contents of this object from the specified stream.
|
/// 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
|
/// Writes the subdivision of the contents of this object (preceeded by a
|
||||||
/// reference to the object itself) to the specified stream if necessary.
|
/// 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) {
|
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();
|
qint32* header = (qint32*)inflated.data();
|
||||||
*header++ = offsetX;
|
*header++ = offsetX;
|
||||||
*header++ = offsetY;
|
*header++ = offsetY;
|
||||||
*header++ = width;
|
*header++ = width;
|
||||||
*header++ = height;
|
*header++ = height;
|
||||||
if (!contents.isEmpty()) {
|
if (!contents.isEmpty()) {
|
||||||
// encode with Paeth filter (see http://en.wikipedia.org/wiki/Portable_Network_Graphics#Filtering)
|
QBuffer buffer(&inflated);
|
||||||
const uchar* src = (const uchar*)contents.constData();
|
buffer.open(QIODevice::WriteOnly | QIODevice::Append);
|
||||||
uchar* dest = (uchar*)inflated.data() + HEIGHTFIELD_DATA_HEADER_SIZE;
|
QImage((const uchar*)contents.constData(), width, height, width * DataBlock::COLOR_BYTES,
|
||||||
*dest++ = *src++;
|
QImage::Format_RGB888).save(&buffer, "JPG");
|
||||||
*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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return qCompress(inflated);
|
return qCompress(inflated);
|
||||||
}
|
}
|
||||||
|
@ -727,35 +703,19 @@ static QByteArray decodeHeightfieldColor(const QByteArray& encoded, int& offsetX
|
||||||
offsetY = *header++;
|
offsetY = *header++;
|
||||||
width = *header++;
|
width = *header++;
|
||||||
height = *header++;
|
height = *header++;
|
||||||
QByteArray contents(inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE, 0);
|
int payloadSize = inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE;
|
||||||
if (!contents.isEmpty()) {
|
if (payloadSize == 0) {
|
||||||
const uchar* src = (const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE;
|
return QByteArray();
|
||||||
uchar* dest = (uchar*)contents.data();
|
}
|
||||||
*dest++ = *src++;
|
QImage image = QImage::fromData((const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE, payloadSize, "JPG");
|
||||||
*dest++ = *src++;
|
if (image.format() != QImage::Format_RGB888) {
|
||||||
*dest++ = *src++;
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
int stride = width * DataBlock::COLOR_BYTES;
|
}
|
||||||
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
|
QByteArray contents(width * height * DataBlock::COLOR_BYTES, 0);
|
||||||
*dest = *src + dest[-DataBlock::COLOR_BYTES];
|
char* dest = contents.data();
|
||||||
}
|
int stride = width * DataBlock::COLOR_BYTES;
|
||||||
for (int y = 1; y < height; y++) {
|
for (int y = 0; y < height; y++, dest += stride) {
|
||||||
*dest = (*src++) + dest[-stride];
|
memcpy(dest, image.constScanLine(y), 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
@ -3718,9 +3678,18 @@ void Heightfield::writeExtra(Bitstream& out) const {
|
||||||
_root->write(state);
|
_root->write(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heightfield::readExtra(Bitstream& in) {
|
void Heightfield::readExtra(Bitstream& in, bool reread) {
|
||||||
if (getWillBeVoxelized()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
MetavoxelLOD lod;
|
MetavoxelLOD lod;
|
||||||
|
@ -3732,7 +3701,9 @@ void Heightfield::readExtra(Bitstream& in) {
|
||||||
|
|
||||||
HeightfieldNodePointer root(new HeightfieldNode());
|
HeightfieldNodePointer root(new HeightfieldNode());
|
||||||
root->read(state);
|
root->read(state);
|
||||||
setRoot(root);
|
if (!reread) {
|
||||||
|
setRoot(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const {
|
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;
|
MetavoxelLOD lod, referenceLOD;
|
||||||
if (in.getContext()) {
|
if (in.getContext()) {
|
||||||
MetavoxelStreamBase* base = static_cast<MetavoxelStreamBase*>(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 };
|
HeightfieldStreamBase base = { in, lod, referenceLOD };
|
||||||
HeightfieldStreamState state = { base, glm::vec2(), 1.0f };
|
HeightfieldStreamState state = { base, glm::vec2(), 1.0f };
|
||||||
|
|
||||||
setRoot(static_cast<const Heightfield*>(reference)->getRoot());
|
|
||||||
bool changed;
|
bool changed;
|
||||||
in >> changed;
|
in >> changed;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
HeightfieldNodePointer root(new HeightfieldNode());
|
HeightfieldNodePointer root(new HeightfieldNode());
|
||||||
root->readDelta(static_cast<const Heightfield*>(reference)->getRoot(), state);
|
root->readDelta(static_cast<const Heightfield*>(reference)->getRoot(), state);
|
||||||
setRoot(root);
|
if (!reread) {
|
||||||
|
setRoot(root);
|
||||||
|
}
|
||||||
} else if (state.becameSubdividedOrCollapsed()) {
|
} 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 bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal);
|
||||||
|
|
||||||
virtual void writeExtra(Bitstream& out) const;
|
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 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 void maybeWriteSubdivision(Bitstream& out);
|
||||||
virtual SharedObject* readSubdivision(Bitstream& in);
|
virtual SharedObject* readSubdivision(Bitstream& in);
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
||||||
case PacketTypeAudioStreamStats:
|
case PacketTypeAudioStreamStats:
|
||||||
return 1;
|
return 1;
|
||||||
case PacketTypeMetavoxelData:
|
case PacketTypeMetavoxelData:
|
||||||
return 11;
|
return 12;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue