mirror planes detection needs work
[laserbrain_demo] / src / renderer.cc
1 #include "renderer.h"
2 #include "rtarg.h"
3 #include "app.h"
4
5 static RenderTarget *rtmirror;
6
7 Renderer::Renderer()
8 {
9         mscn = 0;
10         ropt = RENDER_ALL;
11 }
12
13 Renderer::~Renderer()
14 {
15         destroy();
16 }
17
18 bool Renderer::init()
19 {
20         static bool once;
21         if(!rtmirror && !once) {
22                 once = true;
23                 rtmirror = new RenderTarget;
24                 if(!rtmirror->create(vp_width, vp_height, GL_SRGB)) {
25                         error_log("failed to create mirror render target (%dx%d)\n", vp_width, vp_height);
26                 }
27         }
28
29         return true;
30 }
31
32 void Renderer::destroy()
33 {
34 }
35
36 void Renderer::set_scene(MetaScene *mscn)
37 {
38         this->mscn = mscn;
39 }
40
41 MetaScene *Renderer::get_scene() const
42 {
43         return mscn;
44 }
45
46 // render mirror reflections if ...
47 #define DO_MIRRORS      \
48         mscn->mirrors &&                        /* scene contains mirrors */ \
49         (ropt & RENDER_MIRRORS) &&      /* mirror rendering is enabled */ \
50         rtmirror                                        /* mirror render target succesfully created */
51
52 void Renderer::draw() const
53 {
54         if(!mscn) return;
55
56         if(DO_MIRRORS && current_render_target() != rtmirror) {
57                 // check if the render target needs resizing
58                 if(rtmirror->get_width() != vp_width || rtmirror->get_height() != vp_height) {
59                         if(!rtmirror->resize(vp_width, vp_height)) {
60                                 error_log("failed to resize mirror render target (%dx%d)\n", vp_width, vp_height);
61                                 goto abort_mirrors;
62                         }
63                 }
64
65                 FlatMirror *mir = mscn->mirrors;
66                 while(mir) {
67                         draw_mirror(mir);
68                         mir = mir->next;
69                 }
70         }
71 abort_mirrors:
72
73         int num = (int)mscn->scenes.size();
74         for(int i=0; i<num; i++) {
75                 Scene *scn = mscn->scenes[i];
76
77                 int nobj = (int)scn->objects.size();
78                 for(int j=0; j<nobj; j++) {
79                         // don't draw mirrors, we already did that earlier (if mirror rendering enabled)
80                         if((ropt & RENDER_MIRRORS) && scn->objects[j]->mtl.flat_mirror) {
81                                 continue;
82                         }
83                         draw_object(scn->objects[j]);
84                 }
85         }
86 }
87
88 void Renderer::draw_object(Object *obj) const
89 {
90         bool vis = true;
91         SceneNode *n = obj->node;
92         while(n) {
93                 if(!n->visible) {
94                         vis = false;
95                         break;
96                 }
97                 n = n->get_parent();
98         }
99
100         if(vis) {
101                 obj->draw();
102         }
103 }
104
105 void Renderer::draw_mirror(FlatMirror *mir) const
106 {
107         push_render_target(rtmirror);
108         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
109
110         glMatrixMode(GL_MODELVIEW);
111         glPushMatrix();
112
113         float pdist = dot(mir->plane.normal, mir->plane.pt);
114         Vec4 peq = Vec4(mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z, pdist);
115
116         if(mir->node) {
117                 peq = mir->node->get_matrix() * peq;
118         }
119
120         Mat4 mirmat;
121         mirmat.mirror(peq.x, peq.y, peq.z, peq.w);
122         glMultMatrixf(mirmat[0]);
123
124         glFrontFace(GL_CW);
125         draw();
126         glFrontFace(GL_CCW);
127
128         glPopMatrix();
129         pop_render_target();
130
131         dump_gl_texture(rtmirror->texture()->get_id(), "mirror.ppm");
132
133         int nobj = mir->objects.size();
134         for(int i=0; i<nobj; i++) {
135                 draw_object(mir->objects[i]);
136         }
137 }