1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include "ModelNodeBase.h"
namespace model
{
ModelNodeBase::ModelNodeBase() :
_attachedToShaders(false)
{}
scene::INode::Type ModelNodeBase::getNodeType() const
{
return Type::Model;
}
void ModelNodeBase::onPreRender(const VolumeTest& volume)
{
assert(_renderEntity);
// Attach renderables (or do nothing if everything is up to date)
attachToShaders();
}
void ModelNodeBase::renderHighlights(IRenderableCollector& collector, const VolumeTest& volume)
{
auto identity = Matrix4::getIdentity();
for (const auto& surface : _renderableSurfaces)
{
collector.addHighlightRenderable(*surface, identity);
}
}
std::size_t ModelNodeBase::getHighlightFlags()
{
return Highlight::NoHighlight; // models are never highlighted themselves
}
void ModelNodeBase::onInsertIntoScene(scene::IMapRootNode& root)
{
// Renderables will acquire their shaders in onPreRender
createRenderableSurfaces();
Node::onInsertIntoScene(root);
}
void ModelNodeBase::onRemoveFromScene(scene::IMapRootNode& root)
{
destroyRenderableSurfaces();
Node::onRemoveFromScene(root);
}
void ModelNodeBase::emplaceRenderableSurface(RenderableModelSurface::Ptr&& surface)
{
_renderableSurfaces.emplace_back(std::move(surface));
}
void ModelNodeBase::destroyRenderableSurfaces()
{
detachFromShaders();
_renderableSurfaces.clear();
}
void ModelNodeBase::detachFromShaders()
{
// Detach any existing surfaces. In case we need them again,
// the node will re-attach in the next pre-render phase
for (auto& surface : _renderableSurfaces)
{
surface->detach();
}
_attachedToShaders = false;
}
void ModelNodeBase::attachToShaders()
{
// Refuse to attach without a render entity
if (_attachedToShaders || !_renderEntity) return;
auto renderSystem = _renderSystem.lock();
if (!renderSystem) return;
for (auto& surface : _renderableSurfaces)
{
auto shader = surface->captureFillShader(*renderSystem);
// Skip filtered materials - the wireframe shader itself is always visible
// so filtered surfaces need to be kept from attaching their geometry
if (!shader->isVisible()) continue;
// Solid mode
surface->attachToShader(shader);
// For orthoview rendering we need a wireframe shader
surface->attachToShader(getRenderState() == RenderState::Active ?
surface->captureWireShader(*renderSystem) : _inactiveShader);
// Attach to the render entity for lighting mode rendering
surface->attachToEntity(_renderEntity, shader);
}
_attachedToShaders = true;
}
void ModelNodeBase::queueRenderableUpdate()
{
for (auto& surface : _renderableSurfaces)
{
surface->queueUpdate();
}
}
void ModelNodeBase::transformChangedLocal()
{
Node::transformChangedLocal();
for (auto& surface : _renderableSurfaces)
{
surface->boundsChanged();
}
}
void ModelNodeBase::onVisibilityChanged(bool isVisibleNow)
{
Node::onVisibilityChanged(isVisibleNow);
if (isVisibleNow)
{
attachToShaders();
}
else
{
detachFromShaders();
}
}
void ModelNodeBase::onFiltersChanged()
{
Node::onFiltersChanged();
// When filters change, some of our surfaces might come into view or end up hidden
// Detach existing surfaces, the next rendering pass will rebuild them
detachFromShaders();
}
void ModelNodeBase::setRenderSystem(const RenderSystemPtr& renderSystem)
{
Node::setRenderSystem(renderSystem);
if (renderSystem)
{
_inactiveShader = renderSystem->capture(BuiltInShaderType::WireframeInactive);
}
else
{
_inactiveShader.reset();
}
}
void ModelNodeBase::onRenderStateChanged()
{
Node::onRenderStateChanged();
detachFromShaders();
}
}
|