mirror planes detection needs work
[laserbrain_demo] / src / renderer.cc
index bb274f2..43a96db 100644 (file)
@@ -1,16 +1,31 @@
 #include "renderer.h"
 #include "renderer.h"
+#include "rtarg.h"
+#include "app.h"
+
+static RenderTarget *rtmirror;
 
 Renderer::Renderer()
 {
        mscn = 0;
 
 Renderer::Renderer()
 {
        mscn = 0;
+       ropt = RENDER_ALL;
 }
 
 Renderer::~Renderer()
 {
 }
 
 Renderer::~Renderer()
 {
+       destroy();
 }
 
 bool Renderer::init()
 {
 }
 
 bool Renderer::init()
 {
+       static bool once;
+       if(!rtmirror && !once) {
+               once = true;
+               rtmirror = new RenderTarget;
+               if(!rtmirror->create(vp_width, vp_height, GL_SRGB)) {
+                       error_log("failed to create mirror render target (%dx%d)\n", vp_width, vp_height);
+               }
+       }
+
        return true;
 }
 
        return true;
 }
 
@@ -28,16 +43,43 @@ MetaScene *Renderer::get_scene() const
        return mscn;
 }
 
        return mscn;
 }
 
+// render mirror reflections if ...
+#define DO_MIRRORS     \
+       mscn->mirrors &&                        /* scene contains mirrors */ \
+       (ropt & RENDER_MIRRORS) &&      /* mirror rendering is enabled */ \
+       rtmirror                                        /* mirror render target succesfully created */
+
 void Renderer::draw() const
 {
        if(!mscn) return;
 
 void Renderer::draw() const
 {
        if(!mscn) return;
 
+       if(DO_MIRRORS && current_render_target() != rtmirror) {
+               // check if the render target needs resizing
+               if(rtmirror->get_width() != vp_width || rtmirror->get_height() != vp_height) {
+                       if(!rtmirror->resize(vp_width, vp_height)) {
+                               error_log("failed to resize mirror render target (%dx%d)\n", vp_width, vp_height);
+                               goto abort_mirrors;
+                       }
+               }
+
+               FlatMirror *mir = mscn->mirrors;
+               while(mir) {
+                       draw_mirror(mir);
+                       mir = mir->next;
+               }
+       }
+abort_mirrors:
+
        int num = (int)mscn->scenes.size();
        for(int i=0; i<num; i++) {
                Scene *scn = mscn->scenes[i];
 
                int nobj = (int)scn->objects.size();
                for(int j=0; j<nobj; j++) {
        int num = (int)mscn->scenes.size();
        for(int i=0; i<num; i++) {
                Scene *scn = mscn->scenes[i];
 
                int nobj = (int)scn->objects.size();
                for(int j=0; j<nobj; j++) {
+                       // don't draw mirrors, we already did that earlier (if mirror rendering enabled)
+                       if((ropt & RENDER_MIRRORS) && scn->objects[j]->mtl.flat_mirror) {
+                               continue;
+                       }
                        draw_object(scn->objects[j]);
                }
        }
                        draw_object(scn->objects[j]);
                }
        }
@@ -59,3 +101,37 @@ void Renderer::draw_object(Object *obj) const
                obj->draw();
        }
 }
                obj->draw();
        }
 }
+
+void Renderer::draw_mirror(FlatMirror *mir) const
+{
+       push_render_target(rtmirror);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+
+       float pdist = dot(mir->plane.normal, mir->plane.pt);
+       Vec4 peq = Vec4(mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z, pdist);
+
+       if(mir->node) {
+               peq = mir->node->get_matrix() * peq;
+       }
+
+       Mat4 mirmat;
+       mirmat.mirror(peq.x, peq.y, peq.z, peq.w);
+       glMultMatrixf(mirmat[0]);
+
+       glFrontFace(GL_CW);
+       draw();
+       glFrontFace(GL_CCW);
+
+       glPopMatrix();
+       pop_render_target();
+
+       dump_gl_texture(rtmirror->texture()->get_id(), "mirror.ppm");
+
+       int nobj = mir->objects.size();
+       for(int i=0; i<nobj; i++) {
+               draw_object(mir->objects[i]);
+       }
+}