mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 10:13:15 +02:00
make entity-tree a global. change how network-requests to load model geometry are triggered
This commit is contained in:
parent
47df744552
commit
d09f70239c
10 changed files with 170 additions and 122 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();
|
||||||
|
@ -1995,7 +1995,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
|
||||||
|
@ -2021,7 +2021,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
|
||||||
|
@ -2066,7 +2066,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
|
||||||
|
@ -2389,7 +2389,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();
|
||||||
|
|
||||||
|
@ -2433,7 +2433,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);
|
||||||
|
@ -2501,7 +2501,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() {
|
||||||
|
@ -2540,13 +2540,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);
|
||||||
|
|
||||||
|
@ -2554,11 +2554,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());
|
||||||
|
@ -2907,19 +2907,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);
|
||||||
|
@ -2937,12 +2937,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());
|
||||||
});
|
});
|
||||||
|
@ -2957,9 +2957,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();
|
||||||
|
@ -3781,7 +3781,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) {
|
||||||
|
@ -3903,7 +3903,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;
|
||||||
}
|
}
|
||||||
|
@ -3916,6 +3916,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3967,11 +3970,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) {
|
if (!_physicsEnabled) {
|
||||||
|
if (nearbyEntitiesAreReadyForPhysics()) {
|
||||||
// These stats packets are sent in between full sends of a scene.
|
// These stats packets are sent in between full sends of a scene.
|
||||||
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that
|
// We keep physics disabled until we've recieved a full scene and everything near the avatar in that
|
||||||
// scene is ready to compute its collision shape.
|
// scene is ready to compute its collision shape.
|
||||||
_physicsEnabled = true;
|
_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;
|
||||||
|
@ -4034,7 +4047,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; }
|
||||||
|
@ -451,7 +451,6 @@ private:
|
||||||
PhysicalEntitySimulation _entitySimulation;
|
PhysicalEntitySimulation _entitySimulation;
|
||||||
PhysicsEnginePointer _physicsEngine;
|
PhysicsEnginePointer _physicsEngine;
|
||||||
|
|
||||||
EntityTreeRenderer _entities;
|
|
||||||
EntityTreeRenderer _entityClipboardRenderer;
|
EntityTreeRenderer _entityClipboardRenderer;
|
||||||
EntityTreePointer _entityClipboard;
|
EntityTreePointer _entityClipboard;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -253,108 +281,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
|
|
||||||
|
|
||||||
remapTextures();
|
remapTextures();
|
||||||
} else {
|
{
|
||||||
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
// float alpha = getLocalRenderAlpha();
|
||||||
gpu::Batch& batch = *args->_batch;
|
|
||||||
auto shapeTransform = getTransformToCenter();
|
|
||||||
batch.setModelTransform(Transform()); // we want to include the scale as well
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
if (!_model || _needsModelReload) {
|
||||||
Model* result = NULL;
|
|
||||||
|
|
||||||
if (!renderer) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure our renderer is setup
|
|
||||||
if (!_myRenderer) {
|
|
||||||
_myRenderer = renderer;
|
|
||||||
}
|
|
||||||
assert(_myRenderer == renderer); // you should only ever render on one renderer
|
|
||||||
|
|
||||||
if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) {
|
|
||||||
return _model;
|
|
||||||
}
|
|
||||||
|
|
||||||
_needsModelReload = false; // this is the reload
|
|
||||||
|
|
||||||
// if we have a URL, then we will want to end up returning a model...
|
|
||||||
if (!getModelURL().isEmpty()) {
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
if (_model && QUrl(getModelURL()) != _model->getURL()) {
|
|
||||||
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
|
|
||||||
_needsInitialSimulation = true;
|
|
||||||
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
|
|
||||||
result = _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL());
|
|
||||||
_needsInitialSimulation = true;
|
|
||||||
} else { // we already have the model we want...
|
|
||||||
result = _model;
|
|
||||||
}
|
|
||||||
} else { // if our desired URL is empty, we may need to delete our existing model
|
|
||||||
if (_model) {
|
|
||||||
_myRenderer->releaseModel(_model);
|
|
||||||
result = _model = NULL;
|
|
||||||
_needsInitialSimulation = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderableModelEntityItem::needsToCallUpdate() const {
|
|
||||||
if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_dimensionsInitialized && _model && _model->isActive()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_myRenderer && (!_model || _needsModelReload)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_model) {
|
|
||||||
if (hasAnimation() || jointsMapped()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool movingOrAnimating = isMoving() || isAnimatingSomething();
|
|
||||||
if ((movingOrAnimating ||
|
|
||||||
_needsInitialSimulation ||
|
|
||||||
_model->getTranslation() != getPosition() ||
|
|
||||||
_model->getRotation() != getRotation() ||
|
|
||||||
_model->getRegistrationPoint() != getRegistrationPoint())
|
|
||||||
&& _model->isActive() && _dimensionsInitialized) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderableModelEntityItem::update(const quint64& now) {
|
|
||||||
if (!_dimensionsInitialized && _model && _model->isActive()) {
|
|
||||||
EntityItemProperties properties;
|
|
||||||
auto extents = _model->getMeshExtents();
|
|
||||||
properties.setDimensions(extents.maximum - extents.minimum);
|
|
||||||
|
|
||||||
qCDebug(entitiesrenderer) << "Autoresizing:" << (!getName().isEmpty() ? getName() : getModelURL());
|
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<EntityScriptingInterface>().data(), "editEntity",
|
|
||||||
Qt::QueuedConnection,
|
|
||||||
Q_ARG(QUuid, getEntityItemID()),
|
|
||||||
Q_ARG(EntityItemProperties, properties));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_myRenderer && (!_model || _needsModelReload)) {
|
|
||||||
// TODO: this getModel() appears to be about 3% of model render time. We should optimize
|
// TODO: this getModel() appears to be about 3% of model render time. We should optimize
|
||||||
PerformanceTimer perfTimer("getModel");
|
PerformanceTimer perfTimer("getModel");
|
||||||
getModel(_myRenderer);
|
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
|
||||||
|
getModel(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_model) {
|
if (_model) {
|
||||||
|
@ -400,6 +334,83 @@ void RenderableModelEntityItem::update(const quint64& now) {
|
||||||
_needsInitialSimulation = false;
|
_needsInitialSimulation = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
auto shapeTransform = getTransformToCenter();
|
||||||
|
batch.setModelTransform(Transform()); // we want to include the scale as well
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
|
Model* result = NULL;
|
||||||
|
|
||||||
|
if (!renderer) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure our renderer is setup
|
||||||
|
if (!_myRenderer) {
|
||||||
|
_myRenderer = renderer;
|
||||||
|
}
|
||||||
|
assert(_myRenderer == renderer); // you should only ever render on one renderer
|
||||||
|
|
||||||
|
if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) {
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
|
||||||
|
_needsModelReload = false; // this is the reload
|
||||||
|
|
||||||
|
// if we have a URL, then we will want to end up returning a model...
|
||||||
|
if (!getModelURL().isEmpty()) {
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
if (_model && (QUrl(getModelURL()) != _model->getURL() ||
|
||||||
|
QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) {
|
||||||
|
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
|
||||||
|
_needsInitialSimulation = true;
|
||||||
|
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
|
||||||
|
result = _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL());
|
||||||
|
_needsInitialSimulation = true;
|
||||||
|
} else { // we already have the model we want...
|
||||||
|
result = _model;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_model && _needsInitialSimulation) {
|
||||||
|
PerformanceTimer perfTimer("_model->simulate");
|
||||||
|
_model->simulate(0.0f);
|
||||||
|
}
|
||||||
|
_needsInitialSimulation = false;
|
||||||
|
} else { // if our desired URL is empty, we may need to delete our existing model
|
||||||
|
if (_model) {
|
||||||
|
_myRenderer->releaseModel(_model);
|
||||||
|
result = _model = NULL;
|
||||||
|
_needsInitialSimulation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderableModelEntityItem::needsToCallUpdate() const {
|
||||||
|
return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::update(const quint64& now) {
|
||||||
|
if (!_dimensionsInitialized && _model && _model->isActive()) {
|
||||||
|
EntityItemProperties properties;
|
||||||
|
auto extents = _model->getMeshExtents();
|
||||||
|
properties.setDimensions(extents.maximum - extents.minimum);
|
||||||
|
|
||||||
|
qCDebug(entitiesrenderer) << "Autoresizing:" << (!getName().isEmpty() ? getName() : getModelURL());
|
||||||
|
QMetaObject::invokeMethod(DependencyManager::get<EntityScriptingInterface>().data(), "editEntity",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
Q_ARG(QUuid, getEntityItemID()),
|
||||||
|
Q_ARG(EntityItemProperties, properties));
|
||||||
|
}
|
||||||
|
|
||||||
ModelEntityItem::update(now);
|
ModelEntityItem::update(now);
|
||||||
}
|
}
|
||||||
|
@ -427,17 +438,27 @@ 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...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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;
|
||||||
|
@ -72,6 +73,7 @@ public:
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||||
|
|
||||||
void locationChanged();
|
void locationChanged();
|
||||||
|
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);
|
||||||
|
|
|
@ -76,10 +76,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// model related properties
|
// model related properties
|
||||||
void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
|
virtual void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); }
|
||||||
virtual void setCompoundShapeURL(const QString& 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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue