renderer.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_RENDERER_H)
00023 #define INCLUDED_RENDERER_H
00024
00025 #include "irender.h"
00026 #include "renderable.h"
00027 #include "iselection.h"
00028 #include "cullable.h"
00029 #include "scenelib.h"
00030 #include "math/frustum.h"
00031 #include <vector>
00032
00033 inline Cullable* Instance_getCullable (scene::Instance& instance)
00034 {
00035 return InstanceTypeCast<Cullable>::cast(instance);
00036 }
00037
00038 inline Renderable* Instance_getRenderable (scene::Instance& instance)
00039 {
00040 return InstanceTypeCast<Renderable>::cast(instance);
00041 }
00042
00043 inline VolumeIntersectionValue Cullable_testVisible (scene::Instance& instance, const VolumeTest& volume,
00044 VolumeIntersectionValue parentVisible)
00045 {
00046 if (parentVisible == c_volumePartial) {
00047 Cullable* cullable = Instance_getCullable(instance);
00048 if (cullable != 0) {
00049 return cullable->intersectVolume(volume, instance.localToWorld());
00050 }
00051 }
00052 return parentVisible;
00053 }
00054
00055 template<typename _Walker>
00056 class CullingWalker
00057 {
00058 const VolumeTest& m_volume;
00059 const _Walker& m_walker;
00060 public:
00061 CullingWalker (const VolumeTest& volume, const _Walker& walker) :
00062 m_volume(volume), m_walker(walker)
00063 {
00064 }
00065 bool pre (const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible) const
00066 {
00067 VolumeIntersectionValue visible = Cullable_testVisible(instance, m_volume, parentVisible);
00068 if (visible != c_volumeOutside) {
00069 return m_walker.pre(path, instance);
00070 }
00071 return true;
00072 }
00073 void post (const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible) const
00074 {
00075 return m_walker.post(path, instance);
00076 }
00077 };
00078
00079 template<typename Walker_>
00080 class ForEachVisible: public scene::Graph::Walker
00081 {
00082 const VolumeTest& m_volume;
00083 const Walker_& m_walker;
00084 mutable std::vector<VolumeIntersectionValue> m_state;
00085 public:
00086 ForEachVisible (const VolumeTest& volume, const Walker_& walker) :
00087 m_volume(volume), m_walker(walker)
00088 {
00089 m_state.push_back(c_volumePartial);
00090 }
00091 bool pre (const scene::Path& path, scene::Instance& instance) const
00092 {
00093 VolumeIntersectionValue visible = (path.top().get().visible()) ? m_state.back() : c_volumeOutside;
00094
00095 if (visible == c_volumePartial) {
00096 visible = m_volume.TestAABB(instance.worldAABB());
00097 }
00098
00099 m_state.push_back(visible);
00100
00101 if (visible == c_volumeOutside) {
00102 return false;
00103 } else {
00104 return m_walker.pre(path, instance, m_state.back());
00105 }
00106 }
00107 void post (const scene::Path& path, scene::Instance& instance) const
00108 {
00109 if (m_state.back() != c_volumeOutside) {
00110 m_walker.post(path, instance, m_state.back());
00111 }
00112
00113 m_state.pop_back();
00114 }
00115 };
00116
00117 template<typename Functor>
00118 inline void Scene_forEachVisible (scene::Graph& graph, const VolumeTest& volume, const Functor& functor)
00119 {
00120 graph.traverse(ForEachVisible<CullingWalker<Functor> > (volume, CullingWalker<Functor> (volume, functor)));
00121 }
00122
00123 class RenderHighlighted
00124 {
00125 Renderer& m_renderer;
00126 const VolumeTest& m_volume;
00127 public:
00128 RenderHighlighted (Renderer& renderer, const VolumeTest& volume) :
00129 m_renderer(renderer), m_volume(volume)
00130 {
00131 }
00132 void render (const Renderable& renderable) const
00133 {
00134 switch (m_renderer.getStyle()) {
00135 case Renderer::eFullMaterials:
00136 renderable.renderSolid(m_renderer, m_volume);
00137 break;
00138 case Renderer::eWireframeOnly:
00139 renderable.renderWireframe(m_renderer, m_volume);
00140 break;
00141 }
00142 }
00143 typedef ConstMemberCaller1<RenderHighlighted, const Renderable&, &RenderHighlighted::render> RenderCaller;
00144
00145 bool pre (const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible) const
00146 {
00147 m_renderer.PushState();
00148
00149 if (Cullable_testVisible(instance, m_volume, parentVisible) != c_volumeOutside) {
00150 Renderable* renderable = Instance_getRenderable(instance);
00151 if (renderable) {
00152 renderable->viewChanged();
00153 }
00154
00155 Selectable* selectable = Instance_getSelectable(instance);
00156 if (selectable != 0 && selectable->isSelected()) {
00157 if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent) {
00158 m_renderer.Highlight(Renderer::eFace);
00159 } else if (renderable) {
00160 renderable->renderComponents(m_renderer, m_volume);
00161 }
00162 m_renderer.Highlight(Renderer::ePrimitive);
00163 }
00164
00165 if (renderable) {
00166 render(*renderable);
00167 }
00168 }
00169
00170 return true;
00171 }
00172 void post (const scene::Path& path, scene::Instance& instance, VolumeIntersectionValue parentVisible) const
00173 {
00174 m_renderer.PopState();
00175 }
00176 };
00177
00178 inline void Scene_Render (Renderer& renderer, const VolumeTest& volume)
00179 {
00180 GlobalSceneGraph().traverse(ForEachVisible<RenderHighlighted> (volume, RenderHighlighted(renderer, volume)));
00181 GlobalShaderCache().forEachRenderable(RenderHighlighted::RenderCaller(RenderHighlighted(renderer, volume)));
00182 }
00183
00184 #endif