mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Merge pull request #6612 from sethalves/no-physics-until-ready
No physics until ready
This commit is contained in:
commit
585911fe98
12 changed files with 122 additions and 56 deletions
|
@ -352,6 +352,7 @@ bool setupEssentials(int& argc, char** argv) {
|
||||||
DependencyManager::set<UserInputMapper>();
|
DependencyManager::set<UserInputMapper>();
|
||||||
DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
|
DependencyManager::set<controller::ScriptingInterface, ControllerScriptingInterface>();
|
||||||
DependencyManager::set<InterfaceParentFinder>();
|
DependencyManager::set<InterfaceParentFinder>();
|
||||||
|
DependencyManager::set<EntityTreeRenderer>(true, qApp, qApp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
_frameCount(0),
|
_frameCount(0),
|
||||||
_fps(60.0f),
|
_fps(60.0f),
|
||||||
_physicsEngine(new PhysicsEngine(Vectors::ZERO)),
|
_physicsEngine(new PhysicsEngine(Vectors::ZERO)),
|
||||||
_entities(true, this, this),
|
|
||||||
_entityClipboardRenderer(false, this, this),
|
_entityClipboardRenderer(false, this, this),
|
||||||
_entityClipboard(new EntityTree()),
|
_entityClipboard(new EntityTree()),
|
||||||
_lastQueriedTime(usecTimestampNow()),
|
_lastQueriedTime(usecTimestampNow()),
|
||||||
|
@ -864,7 +864,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
}
|
}
|
||||||
_keyboardFocusHighlight = nullptr;
|
_keyboardFocusHighlight = nullptr;
|
||||||
|
|
||||||
_entities.clear(); // this will allow entity scripts to properly shutdown
|
getEntities()->clear(); // this will allow entity scripts to properly shutdown
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
|
@ -875,7 +875,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
// tell the packet receiver we're shutting down, so it can drop packets
|
// tell the packet receiver we're shutting down, so it can drop packets
|
||||||
nodeList->getPacketReceiver().setShouldDropPackets(true);
|
nodeList->getPacketReceiver().setShouldDropPackets(true);
|
||||||
|
|
||||||
_entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
|
getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
|
||||||
ScriptEngine::stopAllScripts(this); // stop all currently running global scripts
|
ScriptEngine::stopAllScripts(this); // stop all currently running global scripts
|
||||||
|
|
||||||
// first stop all timers directly or by invokeMethod
|
// first stop all timers directly or by invokeMethod
|
||||||
|
@ -921,7 +921,7 @@ void Application::emptyLocalCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
EntityTreePointer tree = _entities.getTree();
|
EntityTreePointer tree = getEntities()->getTree();
|
||||||
tree->setSimulation(NULL);
|
tree->setSimulation(NULL);
|
||||||
|
|
||||||
_octreeProcessor.terminate();
|
_octreeProcessor.terminate();
|
||||||
|
@ -1976,7 +1976,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||||
event->buttons(), event->modifiers());
|
event->buttons(), event->modifiers());
|
||||||
|
|
||||||
|
|
||||||
_entities.mouseMoveEvent(&mappedEvent, deviceID);
|
getEntities()->mouseMoveEvent(&mappedEvent, deviceID);
|
||||||
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
|
_controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
|
||||||
|
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
|
@ -2002,7 +2002,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||||
event->buttons(), event->modifiers());
|
event->buttons(), event->modifiers());
|
||||||
|
|
||||||
if (!_aboutToQuit) {
|
if (!_aboutToQuit) {
|
||||||
_entities.mousePressEvent(&mappedEvent, deviceID);
|
getEntities()->mousePressEvent(&mappedEvent, deviceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
|
||||||
|
@ -2047,7 +2047,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||||
event->buttons(), event->modifiers());
|
event->buttons(), event->modifiers());
|
||||||
|
|
||||||
if (!_aboutToQuit) {
|
if (!_aboutToQuit) {
|
||||||
_entities.mouseReleaseEvent(&mappedEvent, deviceID);
|
getEntities()->mouseReleaseEvent(&mappedEvent, deviceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
|
||||||
|
@ -2370,7 +2370,7 @@ void Application::calibrateEyeTracker5Points() {
|
||||||
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||||
QVector<EntityItemPointer> entities;
|
QVector<EntityItemPointer> entities;
|
||||||
|
|
||||||
auto entityTree = _entities.getTree();
|
auto entityTree = getEntities()->getTree();
|
||||||
auto exportTree = std::make_shared<EntityTree>();
|
auto exportTree = std::make_shared<EntityTree>();
|
||||||
exportTree->createRootElement();
|
exportTree->createRootElement();
|
||||||
|
|
||||||
|
@ -2414,7 +2414,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
|
|
||||||
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
|
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
|
||||||
QVector<EntityItemPointer> entities;
|
QVector<EntityItemPointer> entities;
|
||||||
_entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities);
|
getEntities()->getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities);
|
||||||
|
|
||||||
if (entities.size() > 0) {
|
if (entities.size() > 0) {
|
||||||
glm::vec3 root(x, y, z);
|
glm::vec3 root(x, y, z);
|
||||||
|
@ -2482,7 +2482,7 @@ bool Application::importEntities(const QString& urlOrFilename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
|
QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
|
||||||
return _entityClipboard->sendEntities(&_entityEditSender, _entities.getTree(), x, y, z);
|
return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::initDisplay() {
|
void Application::initDisplay() {
|
||||||
|
@ -2521,13 +2521,13 @@ void Application::init() {
|
||||||
// fire off an immediate domain-server check in now that settings are loaded
|
// fire off an immediate domain-server check in now that settings are loaded
|
||||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||||
|
|
||||||
_entities.init();
|
getEntities()->init();
|
||||||
_entities.setViewFrustum(getViewFrustum());
|
getEntities()->setViewFrustum(getViewFrustum());
|
||||||
|
|
||||||
ObjectMotionState::setShapeManager(&_shapeManager);
|
ObjectMotionState::setShapeManager(&_shapeManager);
|
||||||
_physicsEngine->init();
|
_physicsEngine->init();
|
||||||
|
|
||||||
EntityTreePointer tree = _entities.getTree();
|
EntityTreePointer tree = getEntities()->getTree();
|
||||||
_entitySimulation.init(tree, _physicsEngine, &_entityEditSender);
|
_entitySimulation.init(tree, _physicsEngine, &_entityEditSender);
|
||||||
tree->setSimulation(&_entitySimulation);
|
tree->setSimulation(&_entitySimulation);
|
||||||
|
|
||||||
|
@ -2535,11 +2535,11 @@ void Application::init() {
|
||||||
|
|
||||||
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
|
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
|
||||||
connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity,
|
connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity,
|
||||||
&_entities, &EntityTreeRenderer::entityCollisionWithEntity);
|
getEntities(), &EntityTreeRenderer::entityCollisionWithEntity);
|
||||||
|
|
||||||
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
|
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
|
||||||
// of events related clicking, hovering over, and entering entities
|
// of events related clicking, hovering over, and entering entities
|
||||||
_entities.connectSignalsToSlots(entityScriptingInterface.data());
|
getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
|
||||||
|
|
||||||
_entityClipboardRenderer.init();
|
_entityClipboardRenderer.init();
|
||||||
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
|
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
|
||||||
|
@ -2888,19 +2888,19 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
_avatarUpdate->synchronousProcess();
|
_avatarUpdate->synchronousProcess();
|
||||||
|
|
||||||
if (true || _physicsEnabled) {
|
if (_physicsEnabled) {
|
||||||
PerformanceTimer perfTimer("physics");
|
PerformanceTimer perfTimer("physics");
|
||||||
|
|
||||||
static VectorOfMotionStates motionStates;
|
static VectorOfMotionStates motionStates;
|
||||||
_entitySimulation.getObjectsToDelete(motionStates);
|
_entitySimulation.getObjectsToDelete(motionStates);
|
||||||
_physicsEngine->deleteObjects(motionStates);
|
_physicsEngine->deleteObjects(motionStates);
|
||||||
|
|
||||||
_entities.getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
_entitySimulation.getObjectsToAdd(motionStates);
|
_entitySimulation.getObjectsToAdd(motionStates);
|
||||||
_physicsEngine->addObjects(motionStates);
|
_physicsEngine->addObjects(motionStates);
|
||||||
|
|
||||||
});
|
});
|
||||||
_entities.getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
_entitySimulation.getObjectsToChange(motionStates);
|
_entitySimulation.getObjectsToChange(motionStates);
|
||||||
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
|
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
|
||||||
_entitySimulation.setObjectsToChange(stillNeedChange);
|
_entitySimulation.setObjectsToChange(stillNeedChange);
|
||||||
|
@ -2918,12 +2918,12 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
myAvatar->prepareForPhysicsSimulation();
|
myAvatar->prepareForPhysicsSimulation();
|
||||||
|
|
||||||
_entities.getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
_physicsEngine->stepSimulation();
|
_physicsEngine->stepSimulation();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_physicsEngine->hasOutgoingChanges()) {
|
if (_physicsEngine->hasOutgoingChanges()) {
|
||||||
_entities.getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
_entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID());
|
_entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID());
|
||||||
avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges());
|
avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges());
|
||||||
});
|
});
|
||||||
|
@ -2938,9 +2938,9 @@ void Application::update(float deltaTime) {
|
||||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||||
// deadlock.)
|
// deadlock.)
|
||||||
_entitySimulation.handleCollisionEvents(collisionEvents);
|
_entitySimulation.handleCollisionEvents(collisionEvents);
|
||||||
// NOTE: the _entities.update() call below will wait for lock
|
// NOTE: the getEntities()->update() call below will wait for lock
|
||||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||||
_entities.update(); // update the models...
|
getEntities()->update(); // update the models...
|
||||||
}
|
}
|
||||||
|
|
||||||
myAvatar->harvestResultsFromPhysicsSimulation();
|
myAvatar->harvestResultsFromPhysicsSimulation();
|
||||||
|
@ -3764,7 +3764,7 @@ void Application::clearDomainOctreeDetails() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// reset the model renderer
|
// reset the model renderer
|
||||||
_entities.clear();
|
getEntities()->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::domainChanged(const QString& domainHostname) {
|
void Application::domainChanged(const QString& domainHostname) {
|
||||||
|
@ -3886,7 +3886,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
|
||||||
// Someone logs in close to the table. They receive information about the items on the table before they
|
// Someone logs in close to the table. They receive information about the items on the table before they
|
||||||
// receive information about the table. The items are very close to the avatar's capsule, so they become
|
// receive information about the table. The items are very close to the avatar's capsule, so they become
|
||||||
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
|
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
|
||||||
EntityTreePointer entityTree = _entities.getTree();
|
EntityTreePointer entityTree = getEntities()->getTree();
|
||||||
if (!entityTree) {
|
if (!entityTree) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3899,6 +3899,9 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
|
||||||
|
|
||||||
foreach (EntityItemPointer entity, entities) {
|
foreach (EntityItemPointer entity, entities) {
|
||||||
if (!entity->isReadyToComputeShape()) {
|
if (!entity->isReadyToComputeShape()) {
|
||||||
|
static QString repeatedMessage =
|
||||||
|
LogHandler::getInstance().addRepeatedMessageRegex("Physics disabled until entity loads: .*");
|
||||||
|
qCDebug(interfaceapp) << "Physics disabled until entity loads: " << entity->getID() << entity->getName();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3950,11 +3953,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) {
|
if (!_physicsEnabled) {
|
||||||
// These stats packets are sent in between full sends of a scene.
|
if (nearbyEntitiesAreReadyForPhysics()) {
|
||||||
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that
|
// These stats packets are sent in between full sends of a scene.
|
||||||
// scene is ready to compute its collision shape.
|
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that
|
||||||
_physicsEnabled = true;
|
// scene is ready to compute its collision shape.
|
||||||
|
_physicsEnabled = true;
|
||||||
|
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||||
|
} else {
|
||||||
|
auto characterController = getMyAvatar()->getCharacterController();
|
||||||
|
if (characterController) {
|
||||||
|
// if we have a character controller, disable it here so the avatar doesn't get stuck due to
|
||||||
|
// a non-loading collision hull.
|
||||||
|
characterController->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return statsMessageLength;
|
return statsMessageLength;
|
||||||
|
@ -4017,7 +4030,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
// we can use the same ones from the application.
|
// we can use the same ones from the application.
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
entityScriptingInterface->setPacketSender(&_entityEditSender);
|
entityScriptingInterface->setPacketSender(&_entityEditSender);
|
||||||
entityScriptingInterface->setEntityTree(_entities.getTree());
|
entityScriptingInterface->setEntityTree(getEntities()->getTree());
|
||||||
|
|
||||||
// AvatarManager has some custom types
|
// AvatarManager has some custom types
|
||||||
AvatarManager::registerMetaTypes(scriptEngine);
|
AvatarManager::registerMetaTypes(scriptEngine);
|
||||||
|
|
|
@ -136,7 +136,7 @@ public:
|
||||||
const ViewFrustum* getDisplayViewFrustum() const;
|
const ViewFrustum* getDisplayViewFrustum() const;
|
||||||
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
||||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||||
EntityTreeRenderer* getEntities() { return &_entities; }
|
EntityTreeRenderer* getEntities() { return DependencyManager::get<EntityTreeRenderer>().data(); }
|
||||||
QUndoStack* getUndoStack() { return &_undoStack; }
|
QUndoStack* getUndoStack() { return &_undoStack; }
|
||||||
MainWindow* getWindow() { return _window; }
|
MainWindow* getWindow() { return _window; }
|
||||||
EntityTreePointer getEntityClipboard() { return _entityClipboard; }
|
EntityTreePointer getEntityClipboard() { return _entityClipboard; }
|
||||||
|
@ -444,7 +444,6 @@ private:
|
||||||
PhysicalEntitySimulation _entitySimulation;
|
PhysicalEntitySimulation _entitySimulation;
|
||||||
PhysicsEnginePointer _physicsEngine;
|
PhysicsEnginePointer _physicsEngine;
|
||||||
|
|
||||||
EntityTreeRenderer _entities;
|
|
||||||
EntityTreeRenderer _entityClipboardRenderer;
|
EntityTreeRenderer _entityClipboardRenderer;
|
||||||
EntityTreePointer _entityClipboard;
|
EntityTreePointer _entityClipboard;
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,6 @@ int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const {
|
||||||
result = MSECS_PER_SECOND / THROTTLED_FRAMERATE;
|
result = MSECS_PER_SECOND / THROTTLED_FRAMERATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "New interval " << result;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +137,6 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int newInterval = getDesiredInterval();
|
int newInterval = getDesiredInterval();
|
||||||
qDebug() << newInterval;
|
|
||||||
_timer.start(newInterval);
|
_timer.start(newInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class ZoneEntityItem;
|
||||||
|
|
||||||
|
|
||||||
// Generic client side Octree renderer class.
|
// Generic client side Octree renderer class.
|
||||||
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService {
|
class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||||
|
|
|
@ -12,12 +12,14 @@
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <AbstractViewStateInterface.h>
|
#include <AbstractViewStateInterface.h>
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
#include <Model.h>
|
#include <Model.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
@ -44,6 +46,32 @@ RenderableModelEntityItem::~RenderableModelEntityItem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::setModelURL(const QString& url) {
|
||||||
|
auto& currentURL = getParsedModelURL();
|
||||||
|
ModelEntityItem::setModelURL(url);
|
||||||
|
|
||||||
|
if (currentURL != getParsedModelURL() || !_model) {
|
||||||
|
EntityTreePointer tree = getTree();
|
||||||
|
if (tree) {
|
||||||
|
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::loader() {
|
||||||
|
_needsModelReload = true;
|
||||||
|
EntityTreeRenderer* renderer = DependencyManager::get<EntityTreeRenderer>().data();
|
||||||
|
assert(renderer);
|
||||||
|
if (!_model || _needsModelReload) {
|
||||||
|
PerformanceTimer perfTimer("getModel");
|
||||||
|
getModel(renderer);
|
||||||
|
}
|
||||||
|
if (_model) {
|
||||||
|
_model->setURL(getParsedModelURL());
|
||||||
|
_model->setCollisionModelURL(QUrl(getCompoundShapeURL()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::setDimensions(const glm::vec3& value) {
|
void RenderableModelEntityItem::setDimensions(const glm::vec3& value) {
|
||||||
_dimensionsInitialized = true;
|
_dimensionsInitialized = true;
|
||||||
ModelEntityItem::setDimensions(value);
|
ModelEntityItem::setDimensions(value);
|
||||||
|
@ -223,7 +251,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
// check if the URL has changed
|
// check if the URL has changed
|
||||||
auto& currentURL = getParsedModelURL();
|
auto& currentURL = getParsedModelURL();
|
||||||
if (currentURL != _model->getURL()) {
|
if (currentURL != _model->getURL()) {
|
||||||
qDebug().noquote() << "Updating model URL: " << currentURL.toDisplayString();
|
qCDebug(entitiesrenderer).noquote() << "Updating model URL: " << currentURL.toDisplayString();
|
||||||
_model->setURL(currentURL);
|
_model->setURL(currentURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +346,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
|
|
||||||
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
Model* result = NULL;
|
Model* result = NULL;
|
||||||
|
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -340,7 +368,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
|
|
||||||
// if we have a previously allocated model, but its URL doesn't match
|
// if we have a previously allocated model, but its URL doesn't match
|
||||||
// then we need to let our renderer update our model for us.
|
// then we need to let our renderer update our model for us.
|
||||||
if (_model && QUrl(getModelURL()) != _model->getURL()) {
|
if (_model && (QUrl(getModelURL()) != _model->getURL() ||
|
||||||
|
QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {
|
||||||
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
|
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
|
||||||
_needsInitialSimulation = true;
|
_needsInitialSimulation = true;
|
||||||
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
|
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
|
||||||
|
@ -403,23 +432,34 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
|
auto currentCompoundShapeURL = getCompoundShapeURL();
|
||||||
ModelEntityItem::setCompoundShapeURL(url);
|
ModelEntityItem::setCompoundShapeURL(url);
|
||||||
if (_model) {
|
|
||||||
_model->setCollisionModelURL(QUrl(url));
|
if (getCompoundShapeURL() != currentCompoundShapeURL || !_model) {
|
||||||
|
EntityTreePointer tree = getTree();
|
||||||
|
if (tree) {
|
||||||
|
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderableModelEntityItem::isReadyToComputeShape() {
|
bool RenderableModelEntityItem::isReadyToComputeShape() {
|
||||||
ShapeType type = getShapeType();
|
ShapeType type = getShapeType();
|
||||||
if (type == SHAPE_TYPE_COMPOUND) {
|
|
||||||
|
|
||||||
|
if (type == SHAPE_TYPE_COMPOUND) {
|
||||||
if (!_model) {
|
if (!_model) {
|
||||||
|
EntityTreePointer tree = getTree();
|
||||||
|
if (tree) {
|
||||||
|
QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID()));
|
||||||
|
}
|
||||||
return false; // hmm...
|
return false; // hmm...
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_needsInitialSimulation) {
|
if (_needsInitialSimulation) {
|
||||||
// the _model's offset will be wrong until _needsInitialSimulation is false
|
// the _model's offset will be wrong until _needsInitialSimulation is false
|
||||||
return false;
|
PerformanceTimer perfTimer("_model->simulate");
|
||||||
|
_model->simulate(0.0f);
|
||||||
|
_needsInitialSimulation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!_model->getCollisionURL().isEmpty());
|
assert(!_model->getCollisionURL().isEmpty());
|
||||||
|
|
|
@ -29,7 +29,8 @@ public:
|
||||||
virtual ~RenderableModelEntityItem();
|
virtual ~RenderableModelEntityItem();
|
||||||
|
|
||||||
virtual void setDimensions(const glm::vec3& value) override;
|
virtual void setDimensions(const glm::vec3& value) override;
|
||||||
|
virtual void setModelURL(const QString& url);
|
||||||
|
|
||||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
|
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
|
||||||
virtual bool setProperties(const EntityItemProperties& properties) override;
|
virtual bool setProperties(const EntityItemProperties& properties) override;
|
||||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
|
@ -71,6 +72,8 @@ public:
|
||||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||||
|
|
||||||
|
virtual void loader() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void remapTextures();
|
void remapTextures();
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,8 @@ public:
|
||||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); }
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); }
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); }
|
||||||
|
|
||||||
|
virtual void loader() {} // called indirectly when urls for geometry are updated
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const QByteArray getActionDataInternal() const;
|
const QByteArray getActionDataInternal() const;
|
||||||
|
|
|
@ -1266,3 +1266,12 @@ void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityTree::callLoader(EntityItemID entityID) {
|
||||||
|
// this is used to bounce from the networking thread to the main thread
|
||||||
|
EntityItemPointer entity = findEntityByEntityItemID(entityID);
|
||||||
|
if (entity) {
|
||||||
|
entity->loader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -235,6 +235,9 @@ public:
|
||||||
return _deletedEntityItemIDs.contains(id);
|
return _deletedEntityItemIDs.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void callLoader(EntityItemID entityID);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deletingEntity(const EntityItemID& entityID);
|
void deletingEntity(const EntityItemID& entityID);
|
||||||
void addingEntity(const EntityItemID& entityID);
|
void addingEntity(const EntityItemID& entityID);
|
||||||
|
|
|
@ -74,11 +74,10 @@ public:
|
||||||
_color[GREEN_INDEX] = value.green;
|
_color[GREEN_INDEX] = value.green;
|
||||||
_color[BLUE_INDEX] = value.blue;
|
_color[BLUE_INDEX] = value.blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// model related properties
|
|
||||||
void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
|
|
||||||
virtual void setCompoundShapeURL(const QString& url);
|
|
||||||
|
|
||||||
|
// model related properties
|
||||||
|
virtual void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
|
||||||
|
virtual void setCompoundShapeURL(const QString& url);
|
||||||
|
|
||||||
// Animation related items...
|
// Animation related items...
|
||||||
const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; }
|
const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; }
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; }
|
static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; }
|
||||||
static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; }
|
static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; }
|
||||||
|
|
||||||
virtual bool isReadyToComputeShape() { return false; }
|
virtual bool isReadyToComputeShape() { return true; }
|
||||||
void updateShapeType(ShapeType type) { _shapeType = type; }
|
void updateShapeType(ShapeType type) { _shapeType = type; }
|
||||||
virtual ShapeType getShapeType() const;
|
virtual ShapeType getShapeType() const;
|
||||||
|
|
||||||
|
|
|
@ -319,10 +319,10 @@ void Resource::attemptRequest() {
|
||||||
|
|
||||||
void Resource::finishedLoading(bool success) {
|
void Resource::finishedLoading(bool success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
qDebug().noquote() << "Finished loading:" << _url.toDisplayString();
|
qCDebug(networking).noquote() << "Finished loading:" << _url.toDisplayString();
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
} else {
|
} else {
|
||||||
qDebug().noquote() << "Failed to load:" << _url.toDisplayString();
|
qCDebug(networking).noquote() << "Failed to load:" << _url.toDisplayString();
|
||||||
_failedToLoad = true;
|
_failedToLoad = true;
|
||||||
}
|
}
|
||||||
_loadPriorities.clear();
|
_loadPriorities.clear();
|
||||||
|
@ -339,13 +339,13 @@ void Resource::makeRequest() {
|
||||||
_request = ResourceManager::createResourceRequest(this, _activeUrl);
|
_request = ResourceManager::createResourceRequest(this, _activeUrl);
|
||||||
|
|
||||||
if (!_request) {
|
if (!_request) {
|
||||||
qDebug().noquote() << "Failed to get request for" << _url.toDisplayString();
|
qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString();
|
||||||
ResourceCache::requestCompleted(this);
|
ResourceCache::requestCompleted(this);
|
||||||
finishedLoading(false);
|
finishedLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug().noquote() << "Starting request for:" << _url.toDisplayString();
|
qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString();
|
||||||
|
|
||||||
connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress);
|
connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress);
|
||||||
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
|
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
|
||||||
|
@ -369,7 +369,7 @@ void Resource::handleReplyFinished() {
|
||||||
if (result == ResourceRequest::Success) {
|
if (result == ResourceRequest::Success) {
|
||||||
_data = _request->getData();
|
_data = _request->getData();
|
||||||
auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString());
|
auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString());
|
||||||
qDebug().noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo);
|
qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo);
|
||||||
|
|
||||||
finishedLoading(true);
|
finishedLoading(true);
|
||||||
emit loaded(_data);
|
emit loaded(_data);
|
||||||
|
@ -377,7 +377,7 @@ void Resource::handleReplyFinished() {
|
||||||
} else {
|
} else {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case ResourceRequest::Result::Timeout: {
|
case ResourceRequest::Result::Timeout: {
|
||||||
qDebug() << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal;
|
qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal;
|
||||||
// Fall through to other cases
|
// Fall through to other cases
|
||||||
}
|
}
|
||||||
case ResourceRequest::Result::ServerUnavailable: {
|
case ResourceRequest::Result::ServerUnavailable: {
|
||||||
|
@ -386,7 +386,7 @@ void Resource::handleReplyFinished() {
|
||||||
const int BASE_DELAY_MS = 1000;
|
const int BASE_DELAY_MS = 1000;
|
||||||
if (_attempts++ < MAX_ATTEMPTS) {
|
if (_attempts++ < MAX_ATTEMPTS) {
|
||||||
auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts);
|
auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts);
|
||||||
qDebug().nospace() << "Retrying to load the asset in " << waitTime
|
qCDebug(networking).nospace() << "Retrying to load the asset in " << waitTime
|
||||||
<< "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS;
|
<< "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS;
|
||||||
QTimer::singleShot(waitTime, this, &Resource::attemptRequest);
|
QTimer::singleShot(waitTime, this, &Resource::attemptRequest);
|
||||||
break;
|
break;
|
||||||
|
@ -394,7 +394,7 @@ void Resource::handleReplyFinished() {
|
||||||
// fall through to final failure
|
// fall through to final failure
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
qDebug() << "Error loading " << _url;
|
qCDebug(networking) << "Error loading " << _url;
|
||||||
auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError
|
auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError
|
||||||
: QNetworkReply::UnknownNetworkError;
|
: QNetworkReply::UnknownNetworkError;
|
||||||
emit failed(error);
|
emit failed(error);
|
||||||
|
|
Loading…
Reference in a new issue