mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 09:29:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into pull_out_menu_mess
This commit is contained in:
commit
e1725d1eee
14 changed files with 349 additions and 113 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;
|
||||
|
|
197
examples/billiards.js
Normal file
197
examples/billiards.js
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Pool Table
|
||||
var tableParts = [];
|
||||
var balls = [];
|
||||
|
||||
var LENGTH = 2.84;
|
||||
var WIDTH = 1.42;
|
||||
var HEIGHT = 0.80;
|
||||
var SCALE = 2.0;
|
||||
var BALL_SIZE = 0.05715;
|
||||
var BUMPER_WIDTH = 0.15;
|
||||
var BUMPER_HEIGHT = BALL_SIZE * 2.0;
|
||||
var HOLE_SIZE = BALL_SIZE;
|
||||
var DROP_HEIGHT = BALL_SIZE * 3.0;
|
||||
var GRAVITY = -9.8;
|
||||
var BALL_GAP = 0.001;
|
||||
|
||||
var startStroke = 0;
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
var reticle = Overlays.addOverlay("image", {
|
||||
x: screenSize.x / 2 - 16,
|
||||
y: screenSize.y / 2 - 16,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
function makeTable(pos) {
|
||||
// Top
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: pos,
|
||||
dimensions: { x: LENGTH * SCALE, y: HEIGHT, z: WIDTH * SCALE },
|
||||
color: { red: 0, green: 255, blue: 0 } }));
|
||||
// Long Bumpers
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x - LENGTH / 2.0,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x + LENGTH / 2.0,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x - LENGTH / 2.0,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x + LENGTH / 2.0,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
// End bumpers
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x + (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z },
|
||||
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
|
||||
tableParts.push(Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x - (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||
z: pos.z },
|
||||
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
||||
color: { red: 237, green: 201, blue: 175 } }));
|
||||
|
||||
}
|
||||
|
||||
function makeBalls(pos) {
|
||||
var colors = [{ red: 255, green: 255, blue: 0}, // Yellow
|
||||
{ red: 0, green: 0, blue: 255}, // Blue
|
||||
{ red: 255, green: 0, blue: 0}, // Red
|
||||
{ red: 128, green: 0, blue: 128}, // Purple
|
||||
{ red: 255, green: 165, blue: 0}, // Orange
|
||||
{ red: 0, green: 255, blue: 0}, // Green
|
||||
{ red: 128, green: 0, blue: 0}, // Maroon
|
||||
{ red: 0, green: 0, blue: 0}, // Black
|
||||
{ red: 255, green: 255, blue: 224}, // Light Yellow
|
||||
{ red: 173, green: 216, blue: 230}, // Light Blue
|
||||
{ red: 205, green: 92, blue: 92}, // Indian Red
|
||||
{ red: 218, green: 112, blue: 214}, // Orchid
|
||||
{ red: 218, green: 165, blue: 32}, // GoldenRod
|
||||
{ red: 255, green: 99, blue: 71}, // Tomato
|
||||
{ red: 128, green: 128, blue: 128}]; // Gray
|
||||
|
||||
// Object balls
|
||||
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
|
||||
for (var row = 1; row <= 5; row++) {
|
||||
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
|
||||
for (var spot = 0; spot < row; spot++) {
|
||||
balls.push(Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: ballPosition,
|
||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||
color: colors[balls.length],
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.40,
|
||||
collisionsWillMove: true }));
|
||||
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
|
||||
}
|
||||
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
|
||||
}
|
||||
// Cue Ball
|
||||
ballPosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
|
||||
balls.push(Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: ballPosition,
|
||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.40,
|
||||
collisionsWillMove: true }));
|
||||
}
|
||||
|
||||
function shootCue(velocity) {
|
||||
var DISTANCE_FROM_CAMERA = BALL_SIZE * 5.0 * SCALE;
|
||||
var camera = Camera.getPosition();
|
||||
var forwardVector = Quat.getFront(Camera.getOrientation());
|
||||
var cuePosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
|
||||
var velocity = Vec3.multiply(forwardVector, velocity);
|
||||
var BULLET_LIFETIME = 3.0;
|
||||
var BULLET_GRAVITY = 0.0;
|
||||
bulletID = Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: cuePosition,
|
||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
velocity: velocity,
|
||||
lifetime: BULLET_LIFETIME,
|
||||
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
|
||||
damping: 0.10,
|
||||
density: 1000,
|
||||
ignoreCollisions: false,
|
||||
collisionsWillMove: true
|
||||
});
|
||||
}
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
if ((startStroke > 0) && event.text == "SPACE") {
|
||||
var endTime = new Date().getTime();
|
||||
var delta = endTime - startStroke;
|
||||
shootCue(delta / 100.0);
|
||||
startStroke = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function keyPressEvent(event) {
|
||||
// Fire a cue ball
|
||||
if ((startStroke == 0) && (event.text == "SPACE")) {
|
||||
startStroke = new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
for (var i = 0; i < tableParts.length; i++) {
|
||||
if (!tableParts[i].isKnownID) {
|
||||
tableParts[i] = Entities.identifyEntity(tableParts[i]);
|
||||
}
|
||||
Entities.deleteEntity(tableParts[i]);
|
||||
}
|
||||
for (var i = 0; i < balls.length; i++) {
|
||||
if (!balls[i].isKnownID) {
|
||||
balls[i] = Entities.identifyEntity(balls[i]);
|
||||
}
|
||||
Entities.deleteEntity(balls[i]);
|
||||
}
|
||||
Overlays.deleteOverlay(reticle);
|
||||
}
|
||||
|
||||
var tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
makeTable(tableCenter);
|
||||
makeBalls(tableCenter);
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
|
@ -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);
|
||||
|
|
|
@ -228,7 +228,12 @@ unsigned int Overlays::cloneOverlay(unsigned int id) {
|
|||
} else if (_overlaysWorld.contains(id)) {
|
||||
thisOverlay = _overlaysWorld[id];
|
||||
}
|
||||
return addOverlay(thisOverlay->createClone());
|
||||
|
||||
if (thisOverlay) {
|
||||
return addOverlay(thisOverlay->createClone());
|
||||
}
|
||||
|
||||
return 0; // Not found
|
||||
}
|
||||
|
||||
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -685,41 +685,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);
|
||||
}
|
||||
|
@ -731,35 +707,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;
|
||||
}
|
||||
|
@ -3722,9 +3682,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;
|
||||
|
@ -3736,7 +3705,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 {
|
||||
|
@ -3760,7 +3731,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());
|
||||
|
@ -3770,16 +3741,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);
|
||||
|
||||
|
|
|
@ -158,7 +158,8 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
|
|||
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||
const JSONCallbackParameters& callbackParams,
|
||||
const QByteArray& dataByteArray,
|
||||
QHttpMultiPart* dataMultiPart) {
|
||||
QHttpMultiPart* dataMultiPart,
|
||||
const QVariantMap& propertyMap) {
|
||||
|
||||
QMetaObject::invokeMethod(this, "invokedRequest",
|
||||
Q_ARG(const QString&, path),
|
||||
|
@ -166,13 +167,15 @@ void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessMan
|
|||
Q_ARG(QNetworkAccessManager::Operation, operation),
|
||||
Q_ARG(const JSONCallbackParameters&, callbackParams),
|
||||
Q_ARG(const QByteArray&, dataByteArray),
|
||||
Q_ARG(QHttpMultiPart*, dataMultiPart));
|
||||
Q_ARG(QHttpMultiPart*, dataMultiPart),
|
||||
Q_ARG(QVariantMap, propertyMap));
|
||||
}
|
||||
|
||||
void AccountManager::unauthenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||
const JSONCallbackParameters& callbackParams,
|
||||
const QByteArray& dataByteArray,
|
||||
QHttpMultiPart* dataMultiPart) {
|
||||
const JSONCallbackParameters& callbackParams,
|
||||
const QByteArray& dataByteArray,
|
||||
QHttpMultiPart* dataMultiPart,
|
||||
const QVariantMap& propertyMap) {
|
||||
|
||||
QMetaObject::invokeMethod(this, "invokedRequest",
|
||||
Q_ARG(const QString&, path),
|
||||
|
@ -180,14 +183,16 @@ void AccountManager::unauthenticatedRequest(const QString& path, QNetworkAccessM
|
|||
Q_ARG(QNetworkAccessManager::Operation, operation),
|
||||
Q_ARG(const JSONCallbackParameters&, callbackParams),
|
||||
Q_ARG(const QByteArray&, dataByteArray),
|
||||
Q_ARG(QHttpMultiPart*, dataMultiPart));
|
||||
Q_ARG(QHttpMultiPart*, dataMultiPart),
|
||||
Q_ARG(QVariantMap, propertyMap));
|
||||
}
|
||||
|
||||
void AccountManager::invokedRequest(const QString& path,
|
||||
bool requiresAuthentication,
|
||||
QNetworkAccessManager::Operation operation,
|
||||
const JSONCallbackParameters& callbackParams,
|
||||
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
|
||||
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart,
|
||||
const QVariantMap& propertyMap) {
|
||||
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
|
@ -235,7 +240,9 @@ void AccountManager::invokedRequest(const QString& path,
|
|||
} else {
|
||||
networkReply = networkAccessManager.put(networkRequest, dataMultiPart);
|
||||
}
|
||||
dataMultiPart->setParent(networkReply);
|
||||
|
||||
// make sure dataMultiPart is destroyed when the reply is
|
||||
connect(networkReply, &QNetworkReply::destroyed, dataMultiPart, &QHttpMultiPart::deleteLater);
|
||||
} else {
|
||||
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
if (operation == QNetworkAccessManager::PostOperation) {
|
||||
|
@ -255,6 +262,14 @@ void AccountManager::invokedRequest(const QString& path,
|
|||
}
|
||||
|
||||
if (networkReply) {
|
||||
if (!propertyMap.isEmpty()) {
|
||||
// we have properties to set on the reply so the user can check them after
|
||||
foreach(const QString& propertyKey, propertyMap.keys()) {
|
||||
networkReply->setProperty(qPrintable(propertyKey), propertyMap.value(propertyKey));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!callbackParams.isEmpty()) {
|
||||
// if we have information for a callback, insert the callbackParams into our local map
|
||||
_pendingCallbackMap.insert(networkReply, callbackParams);
|
||||
|
|
|
@ -48,13 +48,15 @@ public:
|
|||
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
||||
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
||||
const QByteArray& dataByteArray = QByteArray(),
|
||||
QHttpMultiPart* dataMultiPart = NULL);
|
||||
QHttpMultiPart* dataMultiPart = NULL,
|
||||
const QVariantMap& propertyMap = QVariantMap());
|
||||
|
||||
void unauthenticatedRequest(const QString& path,
|
||||
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
||||
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
||||
const QByteArray& dataByteArray = QByteArray(),
|
||||
QHttpMultiPart* dataMultiPart = NULL);
|
||||
QHttpMultiPart* dataMultiPart = NULL,
|
||||
const QVariantMap& propertyMap = QVariantMap()) ;
|
||||
|
||||
const QUrl& getAuthURL() const { return _authURL; }
|
||||
void setAuthURL(const QUrl& authURL);
|
||||
|
@ -109,7 +111,8 @@ private:
|
|||
QNetworkAccessManager::Operation operation,
|
||||
const JSONCallbackParameters& callbackParams,
|
||||
const QByteArray& dataByteArray,
|
||||
QHttpMultiPart* dataMultiPart);
|
||||
QHttpMultiPart* dataMultiPart,
|
||||
const QVariantMap& propertyMap);
|
||||
|
||||
QUrl _authURL;
|
||||
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
|
||||
|
|
|
@ -121,14 +121,16 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
|
|||
if (!handleUsername(lookupUrl.authority())) {
|
||||
// we're assuming this is either a network address or global place name
|
||||
// check if it is a network address first
|
||||
if (!handleNetworkAddress(lookupUrl.host()
|
||||
if (handleNetworkAddress(lookupUrl.host()
|
||||
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) {
|
||||
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
} else {
|
||||
// wasn't an address - lookup the place name
|
||||
attemptPlaceNameLookup(lookupUrl.host());
|
||||
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
|
||||
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path());
|
||||
|
||||
}
|
||||
|
||||
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -166,12 +168,14 @@ void AddressManager::handleAPIResponse(QNetworkReply& requestReply) {
|
|||
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
|
||||
QJsonObject dataObject = responseObject["data"].toObject();
|
||||
|
||||
goToAddressFromObject(dataObject.toVariantMap());
|
||||
goToAddressFromObject(dataObject.toVariantMap(), requestReply);
|
||||
|
||||
emit lookupResultsFinished();
|
||||
}
|
||||
|
||||
void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
|
||||
const char OVERRIDE_PATH_KEY[] = "override_path";
|
||||
|
||||
void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const QNetworkReply& reply) {
|
||||
|
||||
const QString DATA_OBJECT_PLACE_KEY = "place";
|
||||
const QString DATA_OBJECT_USER_LOCATION_KEY = "location";
|
||||
|
@ -205,6 +209,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
|
|||
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
|
||||
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
|
||||
|
||||
qDebug() << "Possible domain change required to connect to" << domainHostname
|
||||
<< "on" << DEFAULT_DOMAIN_SERVER_PORT;
|
||||
emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT);
|
||||
} else {
|
||||
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
|
||||
|
@ -213,6 +219,9 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
|
|||
QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
|
||||
QUuid domainID(domainIDString);
|
||||
|
||||
qDebug() << "Possible domain change required to connect to domain with ID" << domainID
|
||||
<< "via ice-server at" << iceServerAddress;
|
||||
|
||||
emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID);
|
||||
}
|
||||
|
||||
|
@ -225,18 +234,29 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
|
|||
QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString();
|
||||
setRootPlaceName(newRootPlaceName);
|
||||
|
||||
// take the path that came back
|
||||
const QString PLACE_PATH_KEY = "path";
|
||||
QString returnedPath = locationMap[PLACE_PATH_KEY].toString();
|
||||
// check if we had a path to override the path returned
|
||||
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
|
||||
|
||||
bool shouldFaceViewpoint = locationMap.contains(LOCATION_API_ONLINE_KEY);
|
||||
|
||||
if (!returnedPath.isEmpty()) {
|
||||
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
|
||||
if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) {
|
||||
qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
|
||||
if (!overridePath.isEmpty()) {
|
||||
if (!handleRelativeViewpoint(overridePath)){
|
||||
qDebug() << "User entered path could not be handled as a viewpoint - " << overridePath;
|
||||
}
|
||||
} else {
|
||||
// take the path that came back
|
||||
const QString PLACE_PATH_KEY = "path";
|
||||
QString returnedPath = locationMap[PLACE_PATH_KEY].toString();
|
||||
|
||||
bool shouldFaceViewpoint = locationMap.contains(LOCATION_API_ONLINE_KEY);
|
||||
|
||||
if (!returnedPath.isEmpty()) {
|
||||
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
|
||||
if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) {
|
||||
qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
qDebug() << "Received an address manager API response with no domain key. Cannot parse.";
|
||||
qDebug() << locationMap;
|
||||
|
@ -262,12 +282,21 @@ void AddressManager::handleAPIError(QNetworkReply& errorReply) {
|
|||
|
||||
const QString GET_PLACE = "/api/v1/places/%1";
|
||||
|
||||
void AddressManager::attemptPlaceNameLookup(const QString& lookupString) {
|
||||
void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath) {
|
||||
// assume this is a place name and see if we can get any info on it
|
||||
QString placeName = QUrl::toPercentEncoding(lookupString);
|
||||
|
||||
QVariantMap requestParams;
|
||||
if (!overridePath.isEmpty()) {
|
||||
requestParams.insert(OVERRIDE_PATH_KEY, overridePath);
|
||||
}
|
||||
|
||||
AccountManager::getInstance().unauthenticatedRequest(GET_PLACE.arg(placeName),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
apiCallbackParameters());
|
||||
apiCallbackParameters(),
|
||||
QByteArray(),
|
||||
NULL,
|
||||
requestParams);
|
||||
}
|
||||
|
||||
bool AddressManager::handleNetworkAddress(const QString& lookupString) {
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
const QString& getRootPlaceName() const { return _rootPlaceName; }
|
||||
void setRootPlaceName(const QString& rootPlaceName);
|
||||
|
||||
void attemptPlaceNameLookup(const QString& lookupString);
|
||||
void attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath = QString());
|
||||
|
||||
void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; }
|
||||
void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
public slots:
|
||||
void handleLookupString(const QString& lookupString);
|
||||
void goToUser(const QString& username);
|
||||
void goToAddressFromObject(const QVariantMap& addressMap);
|
||||
void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply& reply);
|
||||
|
||||
void storeCurrentAddress();
|
||||
|
||||
|
|
|
@ -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