merge from master

This commit is contained in:
SamGondelman 2016-08-08 13:30:39 -07:00
commit 328d3128fa
11 changed files with 181 additions and 57 deletions

View file

@ -739,7 +739,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket);
identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
ResourceCache::setRequestLimit(MAX_CONCURRENT_RESOURCE_DOWNLOADS);
const char** constArgv = const_cast<const char**>(argv);
QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
bool success;
int concurrentDownloads = concurrentDownloadsStr.toInt(&success);
if (!success) {
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
}
ResourceCache::setRequestLimit(concurrentDownloads);
_glWidget = new GLCanvas();
getApplicationCompositor().setRenderingWidget(_glWidget);
@ -3240,6 +3247,18 @@ void Application::init() {
getEntities()->setViewFrustum(_viewFrustum);
}
getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
auto dims = item.getDimensions();
auto maxSize = glm::max(dims.x, dims.y, dims.z);
if (maxSize <= 0.0f) {
return 0.0f;
}
auto distance = glm::distance(getMyAvatar()->getPosition(), item.getPosition());
return atan2(maxSize, distance);
});
ObjectMotionState::setShapeManager(&_shapeManager);
_physicsEngine->init();

View file

@ -529,7 +529,7 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
}
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) {
ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority) {
ModelPointer model = nullptr;
// Only create and delete models on the thread that owns the EntityTreeRenderer
@ -543,6 +543,7 @@ ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString
}
model = std::make_shared<Model>(std::make_shared<Rig>());
model->setLoadingPriority(loadingPriority);
model->init();
model->setURL(QUrl(url));
model->setCollisionModelURL(QUrl(collisionUrl));

View file

@ -28,11 +28,14 @@ class AbstractViewStateInterface;
class Model;
class ScriptEngine;
class ZoneEntityItem;
class EntityItem;
class Model;
using ModelPointer = std::shared_ptr<Model>;
using ModelWeakPointer = std::weak_ptr<Model>;
using CalculateEntityLoadingPriority = std::function<float(const EntityItem& item)>;
// Generic client side Octree renderer class.
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency {
Q_OBJECT
@ -46,6 +49,10 @@ public:
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
virtual void setTree(OctreePointer newTree);
// Returns the priority at which an entity should be loaded. Higher values indicate higher priority.
float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); }
void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; }
void shutdown();
void update();
@ -66,7 +73,7 @@ public:
void reloadEntityScripts();
/// if a renderable entity item needs a model, we will allocate it for them
Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl);
Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl, float loadingPriority = 0.0f);
/// if a renderable entity item needs to update the URL of a model, we will handle that for the entity
Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl);
@ -202,6 +209,10 @@ private:
QList<EntityItemID> _entityIDsLastInScene;
static int _entitiesScriptEngineCount;
CalculateEntityLoadingPriority _calculateEntityLoadingPriorityFunc = [](const EntityItem& item) -> float {
return 0.0f;
};
};

View file

@ -490,7 +490,7 @@ ModelPointer RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
if (!getModelURL().isEmpty()) {
// If we don't have a model, allocate one *immediately*
if (!_model) {
_model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL());
_model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL(), renderer->getEntityLoadingPriority(*this));
_needsInitialSimulation = true;
// If we need to change URLs, update it *after rendering* (to avoid access violations)
} else if ((QUrl(getModelURL()) != _model->getURL() || QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {

View file

@ -52,7 +52,6 @@ public:
bool& keepSearching, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal,
void** intersectedObject, bool precisionPicking) const override;
ModelPointer getModel(EntityTreeRenderer* renderer);
virtual bool needsToCallUpdate() const override;

View file

@ -831,7 +831,9 @@ void Model::setURL(const QUrl& url) {
invalidCalculatedMeshBoxes();
deleteGeometry();
_renderWatcher.setResource(DependencyManager::get<ModelCache>()->getGeometryResource(url));
auto resource = DependencyManager::get<ModelCache>()->getGeometryResource(url);
resource->setLoadPriority(this, _loadingPriority);
_renderWatcher.setResource(resource);
onInvalidate();
}

View file

@ -240,6 +240,8 @@ public:
// returns 'true' if needs fullUpdate after geometry change
bool updateGeometry();
void setLoadingPriority(float priority) { _loadingPriority = priority; }
public slots:
void loadURLFinished(bool success);
void loadCollisionModelURLFinished(bool success);
@ -409,6 +411,10 @@ protected:
bool _collisionGeometryRequestFailed { false };
bool _renderItemsNeedUpdate { false };
private:
float _loadingPriority { 0.0f };
};
Q_DECLARE_METATYPE(ModelPointer)

Binary file not shown.

Binary file not shown.

View file

@ -1,34 +1,18 @@
// Created by james b. pollack @imgntn on 7/2/2016
// Copyright 2016 High Fidelity, Inc.
//
// Creates a beam and target and then teleports you there.
// Creates a beam and target and then teleports you there. Release when its close to you to cancel.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
var inTeleportMode = false;
// instant
// var NUMBER_OF_STEPS = 0;
// var SMOOTH_ARRIVAL_SPACING = 0;
// // slow
// var SMOOTH_ARRIVAL_SPACING = 150;
// var NUMBER_OF_STEPS = 2;
// medium-slow
// var SMOOTH_ARRIVAL_SPACING = 100;
// var NUMBER_OF_STEPS = 4;
// medium-fast
var SMOOTH_ARRIVAL_SPACING = 33;
var NUMBER_OF_STEPS = 6;
//fast
// var SMOOTH_ARRIVAL_SPACING = 10;
// var NUMBER_OF_STEPS = 20;
var TARGET_MODEL_URL = Script.resolvePath("../assets/models/teleport.fbx");
var TARGET_MODEL_URL = Script.resolvePath("../assets/models/teleport-destination.fbx");
var TOO_CLOSE_MODEL_URL = Script.resolvePath("../assets/models/teleport-cancel.fbx");
var TARGET_MODEL_DIMENSIONS = {
x: 1.15,
y: 0.5,
@ -47,7 +31,13 @@ var COLORS_TELEPORT_CANNOT_TELEPORT = {
blue: 141
};
var MAX_AVATAR_SPEED = 0.25;
var COLORS_TELEPORT_TOO_CLOSE = {
red: 255,
green: 184,
blue: 73
};
var TELEPORT_CANCEL_RANGE = 1.5;
function ThumbPad(hand) {
this.hand = hand;
@ -86,29 +76,17 @@ function Teleporter() {
this.rightOverlayLine = null;
this.leftOverlayLine = null;
this.targetOverlay = null;
this.cancelOverlay = null;
this.updateConnected = null;
this.smoothArrivalInterval = null;
this.teleportHand = null;
this.tooClose = false;
this.initialize = function() {
this.createMappings();
this.disableGrab();
};
this.createTargetOverlay = function() {
if (_this.targetOverlay !== null) {
return;
}
var targetOverlayProps = {
url: TARGET_MODEL_URL,
dimensions: TARGET_MODEL_DIMENSIONS,
visible: true
};
_this.targetOverlay = Overlays.addOverlay("model", targetOverlayProps);
};
this.createMappings = function() {
teleporter.telporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random();
teleporter.teleportMappingInternal = Controller.newMapping(teleporter.telporterMappingInternalName);
@ -143,11 +121,56 @@ function Teleporter() {
this.updateConnected = true;
};
this.createTargetOverlay = function() {
if (_this.targetOverlay !== null) {
return;
}
var targetOverlayProps = {
url: TARGET_MODEL_URL,
dimensions: TARGET_MODEL_DIMENSIONS,
visible: true
};
var cancelOverlayProps = {
url: TOO_CLOSE_MODEL_URL,
dimensions: TARGET_MODEL_DIMENSIONS,
visible: true
};
_this.targetOverlay = Overlays.addOverlay("model", targetOverlayProps);
};
this.createCancelOverlay = function() {
if (_this.cancelOverlay !== null) {
return;
}
var cancelOverlayProps = {
url: TOO_CLOSE_MODEL_URL,
dimensions: TARGET_MODEL_DIMENSIONS,
visible: true
};
_this.cancelOverlay = Overlays.addOverlay("model", cancelOverlayProps);
};
this.deleteCancelOverlay = function() {
if (this.cancelOverlay === null) {
return;
}
Overlays.deleteOverlay(this.cancelOverlay);
this.cancelOverlay = null;
}
this.deleteTargetOverlay = function() {
if (this.targetOverlay === null) {
return;
}
Overlays.deleteOverlay(this.targetOverlay);
this.intersection = null;
this.targetOverlay = null;
@ -214,7 +237,7 @@ function Teleporter() {
var rightControllerRotation = Controller.getPoseValue(Controller.Standard.RightHand).rotation;
var rightRotation = Quat.multiply(MyAvatar.orientation, rightControllerRotation)
var rightRotation = Quat.multiply(MyAvatar.orientation, rightControllerRotation);
var rightFinal = Quat.multiply(rightRotation, Quat.angleAxis(90, {
x: 1,
@ -235,11 +258,25 @@ function Teleporter() {
var rightIntersection = Entities.findRayIntersection(teleporter.rightPickRay, true, [], [this.targetEntity]);
if (rightIntersection.intersects) {
this.rightLineOn(rightPickRay.origin, rightIntersection.intersection, COLORS_TELEPORT_CAN_TELEPORT);
if (this.targetOverlay !== null) {
this.updateTargetOverlay(rightIntersection);
if (this.tooClose === true) {
this.deleteTargetOverlay();
this.rightLineOn(rightPickRay.origin, rightIntersection.intersection, COLORS_TELEPORT_TOO_CLOSE);
if (this.cancelOverlay !== null) {
this.updateCancelOverlay(rightIntersection);
} else {
this.createCancelOverlay();
}
} else {
this.createTargetOverlay();
this.deleteCancelOverlay();
this.rightLineOn(rightPickRay.origin, rightIntersection.intersection, COLORS_TELEPORT_CAN_TELEPORT);
if (this.targetOverlay !== null) {
this.updateTargetOverlay(rightIntersection);
} else {
this.createTargetOverlay();
}
}
} else {
@ -275,13 +312,27 @@ function Teleporter() {
if (leftIntersection.intersects) {
this.leftLineOn(leftPickRay.origin, leftIntersection.intersection, COLORS_TELEPORT_CAN_TELEPORT);
if (this.targetOverlay !== null) {
this.updateTargetOverlay(leftIntersection);
if (this.tooClose === true) {
this.deleteTargetOverlay();
this.leftLineOn(leftPickRay.origin, leftIntersection.intersection, COLORS_TELEPORT_TOO_CLOSE);
if (this.cancelOverlay !== null) {
this.updateCancelOverlay(leftIntersection);
} else {
this.createCancelOverlay();
}
} else {
this.createTargetOverlay();
this.deleteCancelOverlay();
this.leftLineOn(leftPickRay.origin, leftIntersection.intersection, COLORS_TELEPORT_CAN_TELEPORT);
if (this.targetOverlay !== null) {
this.updateTargetOverlay(leftIntersection);
} else {
this.createTargetOverlay();
}
}
} else {
this.deleteTargetOverlay();
@ -355,20 +406,44 @@ function Teleporter() {
this.updateTargetOverlay = function(intersection) {
_this.intersection = intersection;
var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP)
var euler = Quat.safeEulerAngles(rotation)
var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP);
var euler = Quat.safeEulerAngles(rotation);
var position = {
x: intersection.intersection.x,
y: intersection.intersection.y + TARGET_MODEL_DIMENSIONS.y / 2,
z: intersection.intersection.z
}
};
this.tooClose = isTooCloseToTeleport(position);
var towardUs = Quat.fromPitchYawRollDegrees(0, euler.y, 0);
Overlays.editOverlay(this.targetOverlay, {
position: position,
rotation: Quat.fromPitchYawRollDegrees(0, euler.y, 0),
rotation: towardUs
});
};
this.updateCancelOverlay = function(intersection) {
_this.intersection = intersection;
var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP);
var euler = Quat.safeEulerAngles(rotation);
var position = {
x: intersection.intersection.x,
y: intersection.intersection.y + TARGET_MODEL_DIMENSIONS.y / 2,
z: intersection.intersection.z
};
this.tooClose = isTooCloseToTeleport(position);
var towardUs = Quat.fromPitchYawRollDegrees(0, euler.y, 0);
Overlays.editOverlay(this.cancelOverlay, {
position: position,
rotation: towardUs
});
};
this.disableGrab = function() {
Messages.sendLocalMessage('Hifi-Hand-Disabler', this.teleportHand);
};
@ -383,10 +458,17 @@ function Teleporter() {
};
this.teleport = function(value) {
if (value === undefined) {
this.exitTeleportMode();
}
if (this.intersection !== null) {
if (this.tooClose === true) {
this.exitTeleportMode();
this.deleteCancelOverlay();
return;
}
var offset = getAvatarFootOffset();
this.intersection.intersection.y += offset;
this.exitTeleportMode();
@ -394,7 +476,6 @@ function Teleporter() {
}
};
this.findMidpoint = function(start, end) {
var xy = Vec3.sum(start, end);
var midpoint = Vec3.multiply(0.5, xy);
@ -433,13 +514,13 @@ function Teleporter() {
if (_this.arrivalPoints.length === 1 || _this.arrivalPoints.length === 0) {
_this.deleteTargetOverlay();
_this.deleteCancelOverlay();
}
}, SMOOTH_ARRIVAL_SPACING);
}
}
//related to repositioning the avatar after you teleport
function getAvatarFootOffset() {
var data = getJointData();
@ -505,7 +586,11 @@ function isMoving() {
} else {
return false;
}
}
};
function isTooCloseToTeleport(position) {
return Vec3.distance(MyAvatar.position, position) <= TELEPORT_CANCEL_RANGE;
};
function registerMappings() {
mappingName = 'Hifi-Teleporter-Dev-' + Math.random();
@ -559,7 +644,7 @@ function registerMappings() {
}, TELEPORT_DELAY)
return;
});
}
};
registerMappings();
@ -573,6 +658,7 @@ function cleanup() {
teleportMapping.disable();
teleporter.disableMappings();
teleporter.deleteTargetOverlay();
teleporter.deleteCancelOverlay();
teleporter.turnOffOverlayBeams();
if (teleporter.updateConnected !== null) {
Script.update.disconnect(teleporter.update);