mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Merge pull request #4989 from ZappoMan/team-teaching-scene-api
TEAM TEACHING - first cut at allowing entities to add/remove their own Scene Items
This commit is contained in:
commit
191fedb598
18 changed files with 128 additions and 63 deletions
|
@ -3403,7 +3403,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
}
|
||||
}
|
||||
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
render::PendingChanges pendingChanges;
|
||||
|
||||
// Make sure the WorldBox is in the scene
|
||||
if (WorldBoxRenderData::_item == 0) {
|
||||
|
|
|
@ -67,7 +67,7 @@ void AvatarManager::init() {
|
|||
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
||||
static_cast<Avatar*>(_myAvatar.get())->_renderItemID = scene->allocateID();
|
||||
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
render::PendingChanges pendingChanges;
|
||||
pendingChanges.resetItem(static_cast<Avatar*>(_myAvatar.get())->_renderItemID, avatarPayloadPointer);
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
@ -152,7 +152,7 @@ AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWe
|
|||
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
||||
static_cast<Avatar*>(avatar.get())->_renderItemID = scene->allocateID();
|
||||
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
render::PendingChanges pendingChanges;
|
||||
pendingChanges.resetItem(static_cast<Avatar*>(avatar.get())->_renderItemID, avatarPayloadPointer);
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
@ -186,7 +186,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
|||
}
|
||||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
render::PendingChanges pendingChanges;
|
||||
pendingChanges.removeItem(avatar->_renderItemID);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
|
|
@ -96,9 +96,13 @@ void EntityTreeRenderer::clear() {
|
|||
OctreeRenderer::clear();
|
||||
_entityScripts.clear();
|
||||
|
||||
// TODO/FIXME - this needs to be fixed... we need to clear all items out of the scene in this case.
|
||||
qDebug() << "EntityTreeRenderer::clear() need to clear the scene... ";
|
||||
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
foreach(auto entity, _entitiesInScene) {
|
||||
entity->removeFromScene(entity, scene, pendingChanges);
|
||||
}
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
_entitiesInScene.clear();
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::init() {
|
||||
|
@ -704,8 +708,8 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
}
|
||||
}
|
||||
|
||||
// hack for models. :(
|
||||
if (entityItem->getType() == EntityTypes::Model) {
|
||||
// hack for models and other entities that don't yet play well with others. :(
|
||||
if (!entityItem->canRenderInScene()) {
|
||||
// render entityItem
|
||||
AABox entityBox = entityItem->getAABox();
|
||||
|
||||
|
@ -1063,12 +1067,13 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
|||
_entityScripts.remove(entityID);
|
||||
|
||||
// here's where we remove the entity payload from the scene
|
||||
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
if (_entityToSceneItems.contains(entityID)) {
|
||||
render::ItemID renderItem = _entityToSceneItems[entityID];
|
||||
pendingChanges.removeItem(renderItem);
|
||||
_viewState->getMain3DScene()->enqueuePendingChanges(pendingChanges);
|
||||
auto entity = static_cast<EntityTree*>(_tree)->findEntityByID(entityID);
|
||||
if (entity && _entitiesInScene.contains(entity)) {
|
||||
render::PendingChanges pendingChanges;
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
entity->removeFromScene(entity, scene, pendingChanges);
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
_entitiesInScene.remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1076,19 +1081,15 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
|
|||
checkAndCallPreload(entityID);
|
||||
|
||||
// here's where we add the entity payload to the scene
|
||||
|
||||
render::Scene::PendingChanges pendingChanges;
|
||||
render::ItemID renderItem = _viewState->getMain3DScene()->allocateID();
|
||||
_entityToSceneItems[entityID] = renderItem;
|
||||
EntityItemPointer entity = static_cast<EntityTree*>(_tree)->findEntityByID(entityID);
|
||||
|
||||
auto renderData = RenderableEntityItem::Pointer(new RenderableEntityItem(entity));
|
||||
auto renderPayload = render::PayloadPointer(new RenderableEntityItem::Payload(renderData));
|
||||
|
||||
pendingChanges.resetItem(renderItem, renderPayload);
|
||||
|
||||
_viewState->getMain3DScene()->enqueuePendingChanges(pendingChanges);
|
||||
_viewState->getMain3DScene()->processPendingChangesQueue();
|
||||
auto entity = static_cast<EntityTree*>(_tree)->findEntityByID(entityID);
|
||||
if (entity && entity->canRenderInScene()) {
|
||||
render::PendingChanges pendingChanges;
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
if (entity->addToScene(entity, scene, pendingChanges)) {
|
||||
_entitiesInScene.insert(entity);
|
||||
}
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
|
||||
|
|
|
@ -187,7 +187,7 @@ private:
|
|||
float _previousStageHour;
|
||||
int _previousStageDay;
|
||||
|
||||
QHash<EntityItemID, render::ItemID> _entityToSceneItems;
|
||||
QSet<EntityItemPointer> _entitiesInScene;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <BoxEntityItem.h>
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableBoxEntityItem : public BoxEntityItem {
|
||||
public:
|
||||
|
@ -24,6 +25,8 @@ public:
|
|||
{ }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
SIMPLE_RENDERABLE()
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -13,17 +13,17 @@
|
|||
#include "RenderableEntityItem.h"
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const RenderableEntityItem::Pointer& payload) {
|
||||
template <> const ItemKey payloadGetKey(const RenderableEntityItemProxy::Pointer& payload) {
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
}
|
||||
|
||||
template <> const Item::Bound payloadGetBound(const RenderableEntityItem::Pointer& payload) {
|
||||
template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload) {
|
||||
if (payload && payload->entity) {
|
||||
return payload->entity->getAABox();
|
||||
}
|
||||
return render::Item::Bound();
|
||||
}
|
||||
template <> void payloadRender(const RenderableEntityItem::Pointer& payload, RenderArgs* args) {
|
||||
template <> void payloadRender(const RenderableEntityItemProxy::Pointer& payload, RenderArgs* args) {
|
||||
if (args) {
|
||||
args->_elementsTouched++;
|
||||
if (payload && payload->entity) {
|
||||
|
|
|
@ -15,19 +15,53 @@
|
|||
#include <render/Scene.h>
|
||||
#include <EntityItem.h>
|
||||
|
||||
class RenderableEntityItem {
|
||||
|
||||
class RenderableEntityItemProxy {
|
||||
public:
|
||||
RenderableEntityItem(EntityItemPointer entity) : entity(entity) { }
|
||||
typedef render::Payload<RenderableEntityItem> Payload;
|
||||
RenderableEntityItemProxy(EntityItemPointer entity) : entity(entity) { }
|
||||
typedef render::Payload<RenderableEntityItemProxy> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
EntityItemPointer entity;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const RenderableEntityItem::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const RenderableEntityItem::Pointer& payload);
|
||||
template <> void payloadRender(const RenderableEntityItem::Pointer& payload, RenderArgs* args);
|
||||
template <> const ItemKey payloadGetKey(const RenderableEntityItemProxy::Pointer& payload);
|
||||
template <> const Item::Bound payloadGetBound(const RenderableEntityItemProxy::Pointer& payload);
|
||||
template <> void payloadRender(const RenderableEntityItemProxy::Pointer& payload, RenderArgs* args);
|
||||
}
|
||||
|
||||
// Mixin class for implementing basic single item rendering
|
||||
class SimpleRenderableEntityItem {
|
||||
public:
|
||||
bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
auto renderData = RenderableEntityItemProxy::Pointer(new RenderableEntityItemProxy(self));
|
||||
auto renderPayload = render::PayloadPointer(new RenderableEntityItemProxy::Payload(renderData));
|
||||
|
||||
pendingChanges.resetItem(_myItem, renderPayload);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myItem);
|
||||
}
|
||||
|
||||
private:
|
||||
render::ItemID _myItem;
|
||||
};
|
||||
|
||||
|
||||
#define SIMPLE_RENDERABLE() \
|
||||
public: \
|
||||
virtual bool canRenderInScene() { return true; } \
|
||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { return _renderHelper.addToScene(self, scene, pendingChanges); } \
|
||||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
|
||||
private: \
|
||||
SimpleRenderableEntityItem _renderHelper;
|
||||
|
||||
|
||||
|
||||
#endif // hifi_RenderableEntityItem_h
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
LightEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
|
||||
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <LineEntityItem.h>
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableLineEntityItem : public LineEntityItem {
|
||||
public:
|
||||
|
@ -23,6 +24,8 @@ public:
|
|||
LineEntityItem(entityItemID, properties) { }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
SIMPLE_RENDERABLE()
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
|
||||
virtual void somethingChangedNotification() { _needsInitialSimulation = true; }
|
||||
|
||||
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <ParticleEffectEntityItem.h>
|
||||
#include <TextureCache.h>
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem {
|
||||
public:
|
||||
|
@ -22,6 +23,8 @@ public:
|
|||
|
||||
void updateQuads(RenderArgs* args, bool textured);
|
||||
|
||||
SIMPLE_RENDERABLE()
|
||||
|
||||
protected:
|
||||
|
||||
int _cacheID;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <SphereEntityItem.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableSphereEntityItem : public SphereEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
@ -23,6 +25,8 @@ public:
|
|||
{ }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
SIMPLE_RENDERABLE()
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
~RenderableTextEntityItem() { delete _textRenderer; }
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f);
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setSourceUrl(const QString& value);
|
||||
virtual bool canRenderInScene() { return false; } // we don't yet play well with others
|
||||
|
||||
private:
|
||||
OffscreenQmlSurface* _webSurface{ nullptr };
|
||||
|
|
|
@ -14,3 +14,4 @@ target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
|
|||
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
|
||||
|
||||
link_hifi_libraries(avatars shared octree gpu model fbx networking animation environment)
|
||||
include_hifi_library_headers(render)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef hifi_EntityItem_h
|
||||
#define hifi_EntityItem_h
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -33,6 +34,11 @@ class EntitySimulation;
|
|||
class EntityTreeElement;
|
||||
class EntityTreeElementExtraEncodeData;
|
||||
|
||||
namespace render {
|
||||
class Scene;
|
||||
class PendingChanges;
|
||||
}
|
||||
|
||||
// these thesholds determine what updates will be ignored (client and server)
|
||||
const float IGNORE_POSITION_DELTA = 0.0001f;
|
||||
const float IGNORE_DIMENSIONS_DELTA = 0.0005f;
|
||||
|
@ -151,6 +157,11 @@ public:
|
|||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
|
||||
{ return 0; }
|
||||
|
||||
virtual bool canRenderInScene() { return false; } // does your entity property render using Render Items and Payloads
|
||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene
|
||||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) { } // by default entity items don't add to scene
|
||||
virtual void render(RenderArgs* args) { } // by default entity items don't know how to render
|
||||
|
||||
static int expectedBytes();
|
||||
|
|
|
@ -68,21 +68,21 @@ void Item::move() {
|
|||
|
||||
}
|
||||
|
||||
void Scene::PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
||||
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
||||
_resetItems.push_back(id);
|
||||
_resetPayloads.push_back(payload);
|
||||
}
|
||||
|
||||
void Scene::PendingChanges::removeItem(ItemID id) {
|
||||
void PendingChanges::removeItem(ItemID id) {
|
||||
_removedItems.push_back(id);
|
||||
}
|
||||
|
||||
void Scene::PendingChanges::moveItem(ItemID id) {
|
||||
void PendingChanges::moveItem(ItemID id) {
|
||||
_movedItems.push_back(id);
|
||||
}
|
||||
|
||||
|
||||
void Scene::PendingChanges::merge(PendingChanges& changes) {
|
||||
void PendingChanges::merge(PendingChanges& changes) {
|
||||
_resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end());
|
||||
_resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end());
|
||||
_removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end());
|
||||
|
@ -106,7 +106,7 @@ void Scene::enqueuePendingChanges(const PendingChanges& pendingChanges) {
|
|||
_changeQueueMutex.unlock();
|
||||
}
|
||||
|
||||
void consolidateChangeQueue(Scene::PendingChangesQueue& queue, Scene::PendingChanges& singleBatch) {
|
||||
void consolidateChangeQueue(PendingChangesQueue& queue, PendingChanges& singleBatch) {
|
||||
while (!queue.empty()) {
|
||||
auto pendingChanges = queue.front();
|
||||
singleBatch.merge(pendingChanges);
|
||||
|
|
|
@ -303,6 +303,27 @@ public:
|
|||
class Engine;
|
||||
class Observer;
|
||||
|
||||
class PendingChanges {
|
||||
public:
|
||||
PendingChanges() {}
|
||||
~PendingChanges() {}
|
||||
|
||||
void resetItem(ItemID id, const PayloadPointer& payload);
|
||||
void removeItem(ItemID id);
|
||||
void moveItem(ItemID id);
|
||||
|
||||
void merge(PendingChanges& changes);
|
||||
|
||||
Payloads _resetPayloads;
|
||||
ItemIDs _resetItems;
|
||||
ItemIDs _removedItems;
|
||||
ItemIDs _movedItems;
|
||||
|
||||
protected:
|
||||
};
|
||||
typedef std::queue<PendingChanges> PendingChangesQueue;
|
||||
|
||||
|
||||
// Scene is a container for Items
|
||||
// Items are introduced, modified or erased in the scene through PendingChanges
|
||||
// Once per Frame, the PendingChanges are all flushed
|
||||
|
@ -340,26 +361,6 @@ public:
|
|||
typedef std::shared_ptr< Observer > ObserverPointer;
|
||||
typedef std::vector< ObserverPointer > Observers;
|
||||
|
||||
class PendingChanges {
|
||||
public:
|
||||
PendingChanges() {}
|
||||
~PendingChanges() {}
|
||||
|
||||
void resetItem(ItemID id, const PayloadPointer& payload);
|
||||
void removeItem(ItemID id);
|
||||
void moveItem(ItemID id);
|
||||
|
||||
void merge(PendingChanges& changes);
|
||||
|
||||
Payloads _resetPayloads;
|
||||
ItemIDs _resetItems;
|
||||
ItemIDs _removedItems;
|
||||
ItemIDs _movedItems;
|
||||
|
||||
protected:
|
||||
};
|
||||
typedef std::queue<PendingChanges> PendingChangesQueue;
|
||||
|
||||
Scene();
|
||||
~Scene() {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue