]> git.tdb.fi Git - libs/gl.git/blob - source/render/zsortedscene.cpp
Copy layout of InterfaceBlock
[libs/gl.git] / source / render / zsortedscene.cpp
1 #include <msp/core/algorithm.h>
2 #include "camera.h"
3 #include "renderer.h"
4 #include "zsortedscene.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 void ZSortedScene::add(Renderable &r)
12 {
13         auto i = lower_bound(content, &r);
14         if(i==content.end() || *i!=&r)
15         {
16                 content.insert(i, &r);
17                 if(!sorted_cache.empty())
18                         sorted_cache.push_back(&r);
19         }
20 }
21
22 void ZSortedScene::remove(Renderable &r)
23 {
24         auto i = lower_bound(content, &r);
25         if(i!=content.end() && *i==&r)
26         {
27                 content.erase(i);
28                 sorted_cache.clear();
29         }
30 }
31
32 void ZSortedScene::set_order(SortOrder o)
33 {
34         order = o;
35 }
36
37 void ZSortedScene::set_reference(DepthReference r)
38 {
39         reference = r;
40 }
41
42 void ZSortedScene::populate_cache() const
43 {
44         if(sorted_cache.empty() && !content.empty())
45         {
46                 sorted_cache.reserve(content.size());
47                 sorted_cache.insert(sorted_cache.end(), content.begin(), content.end());
48         }
49 }
50
51 void ZSortedScene::setup_frame(Renderer &renderer)
52 {
53         populate_cache();
54         for(const SortedRenderable &r: sorted_cache)
55                 r.renderable->setup_frame(renderer);
56 }
57
58 void ZSortedScene::finish_frame()
59 {
60         for(const SortedRenderable &r: sorted_cache)
61                 r.renderable->finish_frame();
62 }
63
64 void ZSortedScene::render(Renderer &renderer, Tag tag) const
65 {
66         if(content.empty())
67                 return;
68
69         populate_cache();
70
71         const Camera *camera = renderer.get_camera();
72         if(!camera)
73         {
74                 for(const SortedRenderable &r: sorted_cache)
75                         r.renderable->render(renderer, tag);
76                 return;
77         }
78
79         const Vector3 &camera_pos = camera->get_position();
80         const Vector3 &look_dir = camera->get_look_direction();
81         float radius_factor = reference-1.0f;
82         float sign = 1.0f-order*2.0f;
83
84         bool use_frustum = setup_frustum(renderer);
85         for(SortedRenderable &r: sorted_cache)
86         {
87                 r.in_frustum = (!use_frustum || !frustum_cull(*r.renderable));
88                 if(!r.in_frustum)
89                         continue;
90
91                 if(const Matrix *matrix = r.renderable->get_matrix())
92                 {
93                         if(const Geometry::BoundingSphere<float, 3> *bsphere = r.renderable->get_bounding_sphere())
94                                 r.depth = dot(*matrix*bsphere->get_center()-camera_pos, look_dir)+bsphere->get_radius()*radius_factor;
95                         else
96                                 r.depth = dot(*matrix*Vector3()-camera_pos, look_dir);
97                         r.depth *= sign;
98                 }
99                 else
100                         r.depth = 0;
101         }
102
103         for(auto i=sorted_cache.begin(), j=i; i!=sorted_cache.end(); ++i)
104                 if(i->in_frustum)
105                 {
106                         if(i!=j)
107                                 swap(*i, *j);
108
109                         if(j!=sorted_cache.begin() && *j<*(j-1))
110                         {
111                                 SortedRenderable sr = *j;
112                                 auto k = j-1;
113                                 *j = *k;
114                                 while(k!=sorted_cache.begin() && sr<*(k-1))
115                                 {
116                                         *k = *(k-1);
117                                         --k;
118                                 }
119                                 *k = sr;
120                         }
121
122                         ++j;
123                 }
124
125         for(auto i=sorted_cache.begin(); (i!=sorted_cache.end() && i->in_frustum); ++i)
126                 i->renderable->render(renderer, tag);
127 }
128
129
130 ZSortedScene::SortedRenderable::SortedRenderable(Renderable *r):
131         renderable(r),
132         in_frustum(false),
133         depth(0.0f)
134 { }
135
136 } // namespace GL
137 } // namespace Msp