mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 21:13:31 +02:00
merge from master
This commit is contained in:
commit
328d3128fa
11 changed files with 181 additions and 57 deletions
interface/src
libraries
entities-renderer/src
render-utils/src
scripts/system
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
BIN
scripts/system/assets/models/teleport-cancel.fbx
Normal file
BIN
scripts/system/assets/models/teleport-cancel.fbx
Normal file
Binary file not shown.
BIN
scripts/system/assets/models/teleport-destination.fbx
Normal file
BIN
scripts/system/assets/models/teleport-destination.fbx
Normal file
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue